不,打开文件不会自动将其读入内存。那将是非常低效的。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
逐行处理(但请阅读理解“ IFS = read -r line”)。
不过,很少需要在shell中逐行处理文件,因为大多数实用程序都是面向行的(请参阅为什么使用shell循环处理文本被认为是不好的做法?)。
我正在从事生物信息学工作,当处理大量的基因组数据时,除非只保留在内存中绝对必要的数据位,否则我将无能为力。例如,当我需要剥离可用于识别VCF文件中包含DNA变体的1 TB数据集中的个体的数据位(因为无法公开该类型的数据)时,我会逐行进行用一个简单的awk
程序进行处理(这是可能的,因为VCF格式是面向行的)。我没有将文件读入内存,在那儿进行处理,然后再写回去!如果文件被压缩,我将通过zcat
或馈入文件gzip -d -c
,由于gzip
进行数据流处理,因此也不会将整个文件读入内存。
即使使用非面向行的文件格式(例如JSON或XML),也可以使用流解析器处理大型文件,而无需将其全部存储在RAM中。
对于可执行文件,它稍微复杂一些,因为共享库可以按需加载和/或在进程之间共享(例如,请参阅加载共享库和RAM使用情况)。
缓存是我在这里没有提到的东西。这是使用RAM来保存经常访问的数据的动作。较小的文件(例如可执行文件)可以由OS缓存,以希望用户对它们进行多次引用。除了第一次读取文件外,随后的访问将访问RAM,而不是磁盘。诸如输入和输出缓冲之类的高速缓存通常对用户基本上是透明的,并且用于高速缓存事物的内存量可能会动态变化,具体取决于应用程序分配的RAM数量等。
1 从技术上讲,大多数程序可能一次使用显式缓冲或隐式地通过标准I / O库执行的缓冲读取输入数据的一部分,然后逐行向用户代码显示该块。与一次读取一个字符相比,读取磁盘块大小的倍数要高效得多。不过,该块的大小很少会超过几千字节。