いいえ、ファイルを開いてもメモリに自動的に読み込まれません。それは非常に非効率です。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行の理解」を読んでください)。
ただし、ほとんどのユーティリティは行指向であるため、シェルでファイルを1行ずつ処理することはほとんど必要ありません(テキストを処理するためにシェルループを使用するのは悪い習慣だと思われる理由を参照してください)。
私はバイオインフォマティクスで働いており、膨大な量のゲノムデータを処理する場合、メモリに絶対に必要なデータの一部だけを保持しない限り、多くのことはできません。たとえば、VCFファイルにDNAバリアントを含む1テラバイトのデータセットから個人を特定するために使用できるデータのビットを取り除く必要がある場合(そのタイプのデータは公開できないため)、1行ずつ実行します単純なawk
プログラムによる処理(VCF形式は行指向なので、これは可能です)。私はファイルをメモリに読み込んでそこで処理し、再び書き戻しません!ファイルが圧縮されている場合、zcat
またはを介してフィードしますgzip -d -c
。これは、gzip
データのストリーム処理を行うため、ファイル全体をメモリに読み込むこともありません。
JSONやXMLのような行指向ではないファイル形式でも、すべてをRAMに保存せずに巨大なファイルを処理できるストリームパーサーがあります。
実行可能ファイルでは、共有ライブラリがオンデマンドでロードされたり、プロセス間で共有されたりする可能性があるため、少し複雑です(参照 たとえば、共有ライブラリのロードとRAM使用量を参照)。
キャッシングは、ここでは言及していません。これは、頻繁にアクセスされるデータを保持するためにRAMを使用するアクションです。ユーザーが多くの参照を行うことを期待して、OSにより小さなファイル(実行可能ファイルなど)がキャッシュされる場合があります。ファイルの最初の読み取りとは別に、後続のアクセスはディスクではなくRAMに対して行われます。入出力のバッファリングなどのキャッシュは、通常、ユーザーに対してほとんど透過的であり、アプリケーションなどによって割り当てられたRAMの量に応じて、キャッシュに使用されるメモリの量が動的に変化する場合があります。
1 技術的には、ほとんどのプログラムはおそらく、明示的なバッファリングを使用するか、標準I / Oライブラリが行うバッファリングを介して暗黙的に入力データのチャンクを一度に読み取り、そのチャンクをユーザーのコードに1行ずつ表示します。ディスクのブロックサイズの倍数を読み取る方が、一度に1文字を読み取るよりもはるかに効率的です。ただし、このチャンクサイズが数キロバイトを超えることはほとんどありません。