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'

代わりに。

おすすめ記事