このコマンドを正常に実行できます。
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/'
同様のことを行うこともできます。)foo
bar
grepで同じことを行うことは、次のgrep -e foo -e bar
ものを含むすべての行を一致させるため、より難しくなります。誰でも foo
または bar
。あなたは次のようなものが必要です
... | grep -E -e 'foo.*bar|bar.*foo'
代わりに。