ティーがstdoutに印刷する順序は保証されていますか?

StackOverflow https://stackoverflow.com/questions/3143452

  •  01-10-2019
  •  | 
  •  

質問

を使用してパイプを分割できます 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 保証されませんか?

役に立ちましたか?

解決

Teeで定義されていませんが、Daenythが言うように、Tシャツがデータを渡すまでWCは終了しません。そのため、通常、ティーはそれまでにawkに渡されます。この例では、awkにカウントを行わせる方が良いかもしれません。

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

マイナス面は、終了するまでの数がわからないということです(データのバッファリングが必要であることを知っています)。あなたの例では、ティーとWCの両方が同じパイプ(awk用のstdin)に接続されているstdoutを持っていますが、順序は未定義です。 CAT(および他のほとんどの配管ツール)を使用して、既知の順序でファイルを組み立てることができます。

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

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

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

ここでの問題は、ティーが猫に物事を書き込もうとして立ち往生することです。ティーから猫までのパイプのデータが多すぎます。

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*

他のヒント

この場合、 wc EOFを待っているので、最初のコマンドが入力を送信するまで戻って(または出力を印刷しません)。他のプロセスに送信するときにそれが定義されているかどうかはわかりません。

線を印刷する前に、AWKをawkに数えてみませんか?

私はあなたがそれを頼りにすることができるとは思わない。 wc ここでは別のプロセスで実行されるため、同期はありません。 私のトライアルの実行は、それが(少なくともバッシュで)である可能性があることを示唆しています。として デーニスは説明します, 、この特定のケースは特別ですが、一緒に試してみてください grep -o line それ以外の wc そして、あなたが何を得るかを見てください。

そうは言っても、私のマッコックスで私は得ます:

$ 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*
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top