.txtファイルの最初の10行と最後の10行を読み取るbashスクリプトを書いています。開始(ヘッド)と完了(テール)を探し、grepを使用して発生数を比較します。ファイルが非常に大きいため、テキスト全体ではなく、ファイルの先頭と末尾のみを読み取ることにしました。ただし、スクリプトを実行すると、大きなファイルが「終了」するまでに長い時間がかかります(最初の10行と最後の10行の読み取りと比較で構成され、1、2秒しかかからないタスクです)。
スクリプトの出力テキストを見ていると、この問題に気づきました。そこで、コマンドラインから直接head/tail(およびスクリプトで実行されているものをシミュレートするためのgrep)コマンドを実行した場合にも、同様の時間がかかるかどうかを確認することにしました。驚いたことに、コマンドはほぼ瞬時に実行されました。これは奇妙だと思い、スクリプトをもう一度実行しました。今回は、スクリプトは、head/tail/grepコマンドをまだ実行していない次の「大きな」ファイルに到達するまで、前にスタックしていたファイルを介して悲鳴を上げていました。
これは私に考えさせられました、bashはキャッシュと同様のコマンドの結果を保存しますか?また、これらのコマンドの原因は次のとおりです。
head -n 10 /file/path/myfile.txt | grep -w -c 'lead Word'
tail -n 10 /file/path/myfile.txt | grep -w -c 'end Word'
実行に時間がかかるのですか?
編集:問題の原因となっているのが上記のヘッド/テールラインであると私が思う理由は、ヘッド/テールの完了時に個別に印刷するエコーラインがあるためです。ファイルの行サイズを確認しましたが、数分以内に終了するファイルよりもそれほど長くはありません。
誰かが私にヘッド/テールがより技術的なレベルでどのように機能するかについてのより詳細な説明を教えてもらえますか?ファイルの「最初/最後のx行」について、非常に基本的な理解があります。
いいえ、出力は実行ごとに変わる可能性があるため、bashはコマンドの出力をキャッシュしません。 bashには、ファイルが別のプロセスによって変更されたかどうかを追跡する確実な方法がありません。これは重要であるため、bash
はキャッシュされた結果がまだ有効かどうかを判断できます。
ただし、ここでは他にもさまざまなことが行われています。シェル(bash
など)を使用すると、システムの複数の部分を同時に操作できます。例えば:
libc
実装。これは、ほとんどすべてのプログラムで時々混乱する動作を引き起こす可能性があります。この場合、最大の貢献者はbash
自体ではなく、ファイルシステムレベルのキャッシュメカニズムがカーネルに実装されていると言えます。ファイルを一度読み取ると、その大部分がファイルシステムキャッシュに保存される可能性があります。これは、この目的のために予約されているメモリの塊です。
ファイルに対して2回目の操作を実行するとき、シェルは物理ハードウェアの読み取りを再度トリガーしませんが、代わりにキャッシュからファイルの内容を取得します。 bashで(再)実行するほぼすべての操作は、ディスクの読み取りに比べて非常に高速です。遅いディスクの読み取りが欠落しているため、bashが実際にコマンドを再実行していることに気付かないのはそのためです。