この質問がSEに適しているかどうかを考えてみました。同意してください。
しばらく前にSEでファイル内のテキストを検索し、検索中のテキストを含む一致する行だけを保持する方法を尋ねました。問題はここにあります: OS Xで端末を使用してファイル内のテキストを検索し、一致する行のみを維持するにはどうすればよいですか?
sed
答えは完璧だったが、なぜそれほど速いのか疑問に思います。私のユースケースでは、合計サイズが約30 GBのファイルがかなりあります。コマンドはsed
約12秒間実行されました。これは私の心を驚かせました(通常のHDDを使用)。 12秒で、このコマンドは各ファイルを切り取り、30 GBのテキストを読み取り、フィルタリングされた対応する行だけを保持します。どのように動作しますか?(または:これはどのような魔法ですか?)
実際のコマンドは次のとおりです。
find . -type f -exec sed -i'' '/\B\/foobar\b/!d' {} \;
答え1
考えられる答えは次のとおりです。
- 断片化のない、または断片化の少ない30Gbファイル:すべてのハードドライブは、大容量ファイルチャンクをキャッシュする機能により、シーケンシャルアクセス(SSDを含む)でより良いパフォーマンスを発揮します。これにより、最高のパフォーマンスを達成できます。順次アクセスはあらゆるレベルのキャッシュに役立ちます。
sed
ストリームエディタは一度に1行ずつ処理します。これはメモリスペースが小さいことを意味します。emacs
WindowsやMacなどのテキストエディタとは異なり、vim
メモリにファイルの完全なコピーを保持する必要はありません。-i
@Rameshが提案したように(を使用して)ファイルをその場で編集しています。ウィキペディアページ)は一時ファイルを作成し、古いファイルになります。
これが意味するのsed
は、ほとんど最小限のファイル操作を実行できることです。つまり、元のファイルの各行を一度読み込み、一致する行だけを記録します。
正規表現の選択はパフォーマンスに影響を与え、時には非常に悪い方法で影響を与えます。コーディングホラーブログ。
答え2
良い例は、一時sed
ファイルを使用して実際にコンテンツを保存してから元のファイルを置き換えることです。たとえば、これを見つけるために簡単なテストを実行できます。
cat test
This is a test file.
次に、実行ls -li
してinode番号を確認します。
ls -li test
2368770 -rw-r--r-- 1 root root 22 Sep 12 08:46 test
次に、次のsed
コマンドを実行して空行を追加します。
sed -i 's/2/B/' test
ファイルを変更したら、ls
再度コマンドを実行してinode番号を確認します。
ls -li test
2368753 -rw-r--r-- 1 root root 22 Sep 12 08:48 test
実際には、inode番号が変更されたことを確認できます。したがって、同じファイルにコピーするのではなく、新しい一時ファイルを作成sed
し、内容を新しい一時ファイルにコピーしてから、ソースファイルを削除してソースファイルと同期してtmpファイルの名前を変更すると、ファイル操作が実際に高速になります。
から引用ウィキペディアページ、
sed は行指向のテキスト処理ユーティリティです。入力ストリームまたはファイルからパターン空間と呼ばれる内部バッファにテキストを1行ずつ読み込みます。 1行を読むたびにループが始まります。パターン空間の場合、sed は sed スクリプトで指定された 1 つ以上の操作を適用します。 sedは、テキストの操作を指定する約25のコマンドでプログラミング言語を実装します。各行に対してスクリプトを実行した後、sedは通常パターンスペース(スクリプトによって変更された入力行)を出力し、次の行でループを再開します。
パターンスペースとホールドスペースの概念についてもっと知りたい場合は、sed
答えを読んでください。ここ。
sedがファイルを1行ずつ読み取ると、現在読み取られた行がパターンバッファ(パターンスペース)に挿入されます。モードバッファは、現在の情報が格納されているスクラッチパッドである一時バッファと同じです。 sedに印刷するように指示すると、パターンバッファが印刷されます。
予約されたバッファ/予約スペースは長期ストレージと同じであるため、sedが他の行を処理している間に何かをキャプチャ、保存、および再利用できます。予約済みスペースを直接処理せずに、代わりに何かを実行するには、パターンスペースにコピーまたは追加する必要があります。