它不是由 tee 定义的,但正如 Daenyth 所说,在 tee 完成传递数据之前 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 的标准输入),但顺序未定义。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
这里的问题是 tee 在尝试向 cat 写东西时会卡住,而 cat 想先用 wcout 完成。从 tee 到 cat 的管道数据太多了。
编辑关于 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*