tailの後に2回grepを実行できないのはなぜですか?

tailの後に2回grepを実行できないのはなぜですか?

このコマンドを正常に実行できます。

tail -f my_file.txt | grep foo

文字列を含む行のみを表示し、foo常に表示します。

しかし、このコマンドを実行すると:

tail -f my_file.txt | grep foo | grep bar

foo一部にとが含まれていても行は表示されませんbar

私は一度の呼び出しで複数のモードを使用する解決策があることを知っていますが、grepこの回線がなぜ失敗するのか疑問に思います。

答え1

これは、Cランタイムライブラリのデフォルトの動作は、stdoutが端末に接続されていない限り、データブロック全体(通常は数キロバイト)が書き込まれるまでstdoutへの書き込みをバッファリングするためです。

中間のgrepがブロック全体を印刷すると出力が得られますが、次のブロックがいっぱいになるのを待つ必要があります。これはスループットの最適化であり、leftコマンドが特定のタスクのみを実行し、いくつかのタスクを待つのではなくシャットダウンしたときにうまく機能します。

GNU grepには--line-bufferedそのバッファリングをオフにするオプションがあるので、これはうまく機能します。

tail -f my_file.txt | grep --line-buffered foo | grep bar

最後の項目はgrep端末に印刷されるため、デフォルトではラインバッファリングされ、オプションは必要ありません。

バラより パイプラインのバッファリングをオフにするバッファリング問題に対する一般的な解決法


2つのgrepを使用するこの特別なケースでは、Stéphane Chazelasが説明で述べたように、単一のAWKを代わりに使用できます。

tail -f my_file.txt | awk '/foo/ && /bar/'

(しかし、ラインをキャプチャしますが、使用せずにawk '/foo/ && !/bar/'同様のことを行うこともできます。)foobar

grepで同じことを行うことは、次のgrep -e foo -e barものを含むすべての行を一致させるため、より難しくなります。誰でも foo または bar。あなたは次のようなものが必要です

... | grep -E -e 'foo.*bar|bar.*foo'

代わりに。

答え2

ブールの観点から見ると期待しているようです。金持ちまたはバーgrepを使用しますが、実行する方法で期待する必要があります。金持ちそしてバー- grepさ​​れる唯一の行バー合格した人金持ちまず、グレブです。

foo/bar を標準出力に表示するには、以下を使用する必要があります。

tail -f my_file.txt | grep "foo|bar"

「pretty|much|like|this」と同じくらい多くのキーワードを追加できます。ただし、引用符を忘れないでください。 (または使用\|引用符がない\|複数の用語)

第二のポイント:だからテール-f(下)your_file.txtに特定の時間に両方のキーワードが追加された行がない可能性があり、通常は予想されるコンテンツがあることが知られているファイルの共有を切り取るのが最善です。

tail -n 500 my_file.txt > my_sample.txt

そこで既知のテキストを使用して、目的のgrep操作を試すことができます。 (最後の500行で十分です。必要に応じて調整してください。)

関連情報