web-dev-qa-db-ja.com

grepからawkへのパイピングが機能しない

私はファイルログの進行中のgreptailを試み、n番目のWordを行から取得しています。ファイルの例:

$ cat > test.txt <<EOL
Beam goes blah
John goes hey
Beam goes what?
John goes forget it
Beam goes okay
Beam goes bye
EOL
^C

tailを実行すると:

$ tail -f test.txt
Beam goes blah
John goes hey
Beam goes what?
John goes forget it
Beam goes okay
Beam goes bye
^C

もしgrepそのtail

$ tail -f test.txt | grep Beam
Beam goes blah
Beam goes what?
Beam goes okay
Beam goes bye
^C

しかし、もし私がawkそのgrep

$ tail -f test.txt | grep Beam | awk '{print $3}'

どれだけ待っても何も。ストリームの動作に関係しているのではないかと思います。

誰か手がかりはありますか?

35

おそらくgrepからの出力バッファリングです。 grep --line-bufferedで無効にできます。

ただし、grepからの出力をawkにパイプする必要はありません。 awkは、すべて単独で正規表現のパターンマッチングを実行できます。

tail -f test.txt | awk '/Beam/ {print $3}'

57
cas

tail -f test.txt | awk '/Beam/{print $3}'を使用するとうまくいきます。 tail -f test.txt | grep --line-buffered Beam | awk '{print $3}'(gnu grep)も使用できます。

ここでの問題は、awkがデータを1行ずつ、または1つの大きなデータブロックとして受信したかどうかです。 GNUバージョンのgrepはより効率的であるため、より大きなブロックで出力を送信しますが、awkは行ごとに出力するために行ごとに読み取る必要があります。

つまり、grepはバッファがいっぱいになったときにのみデータを送信し、awkはそのバッファがいっぱいになるのを待っているため、何も送信していません。

8
Arcege

--line-bufferedオプションgrep

4
choroba