grep用のリダイレクトとパイプ

grep用のリダイレクトとパイプ

STDOUTに出力するチェックサムプロセスを実行するスクリプトを作成しています。その後、OKまたはFAILEDと一致する行を見つけて、一致するものに対して他の操作(たとえば、端末やログへの出力)を実行しようとします。 YouTubeの動画をたくさん見て、リダイレクトについてたくさん読んでいますが、リダイレクトが正確にどのように機能するかを理解していないようです。私がしたいのは、一致しないテキストを食べずにSTDOUTを複数のgrepにリンクすることです。

以下は、1行に1つの動物名(DOG、CAT、PONY、RHINO、DEER、FOX)を含むテキストファイル、md5sumの代わりにcatを使用して試した概念です。

{ cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3> results.txt

これが私が期待していたものです。ここで私が理解するのは、ファイルをキャッティングしてからSTDOUT(fd1)に書き込まれた内容を指すfd3を開くことです。 grepはfd1のすべてを食べるので、明示的にcatのSTDOUTをfd3に送り、次にSTDOUTをgrepにパイプします。 GrepはDOGに一致する行を印刷し、catでfd3に書き込まれたすべてのテキストがresults.txtファイルにプッシュされます。

追加のテキストを見つけるために別のgrepをリンクするには、fd3データをSTDOUTとして指定し、明示的にfd3として返し、STDOUTを新しいgrepにパイプする必要があります。

{ { cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3>&1 | tee /dev/fd/3 | grep PONY; } 3> results.txt

ここでの最初の問題は、最初のgrepのSTDOUTが端末に印刷されるのではなく、2番目にfd3にプッシュされることです。これでresults.txtが重複し、最初のgrepで画面に何も印刷されません。これがリダイレクトの私の理解が崩れる場所です。何が起こっているのか理解していますが、簡単な解決策が見つかりません。

STDOUTをgrepし、結果を画面に印刷し、各GREPに渡す元のテキストを変更せずに、元のテキストを別のgrep、3番目、4番目などに渡したいと思います。以降の各grepはそうではありません。画面に印刷する必要がある以前の「一致」を食べます。

変数を保存して複数行にわたってgrepを呼び出すことでこれを行うことができますが、最初のコマンド全体が完了するまで待つ必要があります。私が開発しているアプリケーションでは、プロセス全体が完了するまで1時間空の画面しか表示されませんが、チェックサム中にリアルタイムの結果を確認したいと思います。私が間違っていることの明確な説明は非常に役立ちます。ありがとうございます!

編集する

私はcatの正確な使い方が意味をなさないことを知っており、概念を示すためにそれを使用しています。この概念を適用するスクリプトでは、最初のコマンドは実際には次のようになります。

md5sum -c checksum.md5

チェックサムファイルを読み取り、ソースを再ハッシュし、パススルー/失敗行をSTDOUTに出力します。その後、このストリームをgrepして結果を別のログおよび/またはターミナル出力に送信したかったのですが、catが問題を説明するより簡単な方法のようです。これは、すべてのコマンドをフィルタリングし、次のストリームをgrepするために適用できるためです。検索、MD5、LSなど

ベストアンサー1

プロセスの置き換えにより、必要な操作をよりよく実行できます。

  1. 元のコマンドにできるだけ近づけます。

    cat test.txt | tee >(grep DOG) >(grep PONY) >results.txt
    
  2. 役に立たないcatの使用を排除します。

    <test.txt tee >(grep DOG) >(grep PONY) >results.txt
    

    または:

    tee >(grep DOG) >(grep PONY) <test.txt >results.txt
    

おすすめ記事