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