Нет, файл не считывается автоматически в память при его открытии. Это было бы ужасно неэффективно. sed
, например, считывает свой ввод строка за строкой, как и многие другие инструменты Unix. Редко приходится хранить в памяти больше, чем текущая строка.
С awk
то же самое. Он считывает запись за раз, что по умолчанию является строкой. Если вы храните часть входных данных в переменных, то это будет лишним, конечно 1 .
У некоторых людей есть привычка делать такие вещи, как
for line in $(cat file); do...; done
Поскольку оболочке придется полностью расширить $(cat file)
подстановку команд перед запуском даже первой итерации цикла for
, этот будет считывать всю file
в память (в память, используемую оболочкой, выполняющей цикл for
). Это немного глупо, а также неэлегантно. Вместо этого следует
while IFS= read -r line; do...; done
Это будет обрабатывать file
строку за строкой (, но читать Понимание "IFS= читать -r строку").
Построчная обработка файлов в оболочке требуется редко, так как большинство утилит в любом случае -ориентированы на строки (см. Почему использование цикла оболочки для обработки текста считается плохой практикой?).
Я работаю в области биоинформатики, и при обработке огромных объемов геномных данных я мало что смог бы сделать, если бы не хранил в памяти только те биты данных, которые были абсолютно необходимы. Например, когда мне нужно удалить биты данных, которые можно использовать для идентификации людей, из набора данных объемом 1 терабайт, содержащего варианты ДНК в файле VCF (, потому что этот тип данных не может быть обнародован ), я выполнять построчную обработку с помощью простой awk
программы (это возможно, поскольку формат VCF построчно -ориентирован ). Я не читаю файл в память, не обрабатываю его там и не записываю обратно! Если бы файл был сжат, я бы скармливал его через zcat
или gzip -d -c
, что, поскольку gzip
выполняет потоковую обработку данных, также не считывало бы весь файл в память.
Даже для форматов файлов, которые не ориентированы на строки, например JSON или XML, существуют потоковые синтаксические анализаторы, которые позволяют обрабатывать огромные файлы, не сохраняя их все в оперативной памяти.
С исполняемыми файлами все немного сложнее, так как общие библиотеки могут загружаться по требованию и/или использоваться совместно процессами (см. Загрузка общих библиотек и использование оперативной памяти , например ).
Кэширование — это то, о чем я здесь не упоминал. Это действие по использованию оперативной памяти для хранения часто используемых фрагментов данных. Файлы меньшего размера (, например исполняемые файлы ), могут кэшироваться ОС в надежде, что пользователь будет делать на них много ссылок. Помимо первого чтения файла, последующие обращения будут осуществляться к оперативной памяти, а не к диску. Кэширование, как и буферизация ввода и вывода, обычно в значительной степени прозрачно для пользователя, и объем памяти, используемый для кэширования, может динамически изменяться в зависимости от объема ОЗУ, выделенного приложениями и т. д.
1Технически, большинство программ, вероятно, считывают часть входных данных за раз,либо с использованием явной буферизации, либо неявно с помощью буферизации, которую выполняют стандартные библиотеки ввода-вывода, а затем представить этот фрагмент построчно в пользовательском коде. Гораздо эффективнее читать кратное размеру блока диска, чем, например. персонаж за раз. Однако размер этого фрагмента редко превышает несколько килобайт.
Похоже, что в Zsh на вашем сервере Ubuntu у вас может быть функция Git _git
в вашем $fpath
перед функцией Zsh _git
. Версия Git — это просто автоматический порт дополнения Bash, и в ней отсутствуют многие функции, которые есть в версии Zsh.
Чтобы узнать, так ли это, выполните ls ${^fpath}/_git(N)
на обеих машинах и сравните. Когда вы найдете проблемный файл, удалите его или убедитесь, что файл Zsh стоит первым.