3

tee次のようにLinuxでコマンドを使用してパイプを分割できます

printf "line1\nline2\nline3\n" | tee >(wc -l ) | (awk '{print "this is awk: "$0}')

出力を生成する

this is awk: line1
this is awk: line2
this is awk: line3
this is awk: 3

私の質問ですが、その印刷順序は保証されていますか? 行数をカウントするtee分割パイプは常に最後に出力されますか? 常に最初に印刷する方法はありますか?それとも、印刷の順序はtee保証されませんか?

4

3 に答える 3

2

teeによって定義されていませんが、Daenythが言うように、teがデータの受け渡しを完了するまでwcは終了しません。したがって、通常、teeはそれまでにawkにデータを渡します。この場合、awkにカウントを行わせる方がよい場合があります。

echo -ne {one,two,three,four}\\n | \
awk '{print "awk processing line " NR ": "$0} END {print "Awk saw " NR " lines"}'

欠点は、終了するまで番号がわからないことです(データをバッファリングする必要があることを知っています)。あなたの例では、teeとwcの両方が同じパイプ(awkの場合はstdin)に接続されたstdoutを持っていますが、順序は定義されていません。cat(および他のほとんどのパイプツール)を使用して、既知の順序でファイルを組み立てることができます。

bashコプロセス(coproc)や名前付きパイプ(mkfifoまたはmknod p)など、使用できるより高度な配管技術があります。後者はファイルシステム内の名前を取得し、他のプロセスに渡すことができますが、それらをクリーンアップして衝突を回避する必要があります。tempfileまたは$$がそのために役立つ場合があります。パイプはサイズが制限されていることが多く、書き込みをブロックするだけなので、データをバッファリングするためのものではありません。

パイプが間違った解決策である例:

mkfifo wcin wcout
wc -l < wcin > wcout &
yes | dd count=1 bs=8M | tee wcin | cat -n wcout - | head

ここでの問題は、最初にwcoutで終了したい猫に物事を書き込もうとしてTシャツがスタックすることです。ティーからキャットへのパイプのデータが多すぎます。

dmckeeの回答に関する編集:はい、順序は繰り返し可能である可能性がありますが、保証されていません。これは、スケール、スケジューリング、およびバッファーサイズの問題です。このGNU/Linuxボックスでは、例は数千行後に分割され始めます。

seq -f line%g 20000 | tee >(awk '{print "*" $0 "*"}' ) | \
(awk '{print "this is awk: "$0}') | less
this is awk: line2397
this is awk: line2398
this is awk: line2*line1*
this is awk: *line2*
this is awk: *line3*
于 2010-06-29T18:59:17.700 に答える
1

この場合、wcは EOF を待っていると思われるため、最初のコマンドが入力の送信を完了するまで返さない (または出力を出力する) のに対し、awk は行ごとに動作するため、常に最初に出力します。他のプロセスに送信するときに定義されているかどうかはわかりません。

行自体を印刷する前に、awk で行をカウントしないのはなぜですか?

于 2010-06-29T18:18:15.127 に答える
0

頼りにできないと思います。ここwcは別のプロセスで実行されるため、同期はありません。私の試運転は、それが(少なくともbashでは)あるかもしれないことを示唆しています。Daenythが説明しているように、この特定のケースは特別ですが、grep -o line代わりに試してみて、wc何が得られるかを確認してください。

そうは言っても、私のMacBooxでは次のようになります。

$ printf "line1\nline2\nline3\nline4\nline5\n" | tee >(grep -o line ) | (awk '{print "this is awk: "$0}')
this is awk: line1
this is awk: line2
this is awk: line3
this is awk: line4
this is awk: line5
this is awk: line
this is awk: line
this is awk: line
this is awk: line
this is awk: line

非常に一貫して。確かに、bashのmanページをよく読む必要があります。

同様に:

$ printf "line1\nline2\nline3\nline4\nline5\n" | tee >(awk '{print "*" $0 "*"}' ) | (awk '{print "this is awk: "$0}')
this is awk: line1
this is awk: line2
this is awk: line3
this is awk: line4
this is awk: line5
this is awk: *line1*
this is awk: *line2*
this is awk: *line3*
this is awk: *line4*
this is awk: *line5*

毎回...そして

$ printf "line1\nline2\nline3\nline4\nline5\n" | tee >(awk '{print "*" $0 "*"}' ) | (grep line)
line1
line2
line3
line4
line5
*line1*
*line2*
*line3*
*line4*
*line5*
于 2010-06-29T19:00:43.873 に答える