sed 和 tee 在管道中一起工作时不再表现得像流

sed and tee when working together in pipes no longer behaves like stream

任何人都可以帮助解释为什么单独使用时 sed 和 tee 看起来像流,但结合使用时却不像流?

您可以看到 stdout 如何逐渐流式传输到 stdout。

但是当一起使用时,您只能在管道中的主进程执行结束时看到标准输出。

示例:

注:

perl -pe "system 'sleep .03'"

只是为了限制标准输出以查看最终标准输出逐渐建立

sed $'s,\x1b\[[0-9;]*[a-zA-Z],,g'

用于去除颜色


printf "

first line
\e[32msecond\e[0m line
\e[33mthird\e[0m line
\e[35mfourth\e[0m line
\e[31mfifth\e[0m line
last line

" | perl -pe "system 'sleep .03'" | sed $'s,\x1b\[[0-9;]*[a-zA-Z],,g'


^^^ 在上面的例子中你可以清楚地看到 stdout 正在逐步构建


printf "

first line
\e[32msecond\e[0m line
\e[33mthird\e[0m line
\e[35mfourth\e[0m line
\e[31mfifth\e[0m line
last line

" | perl -pe "system 'sleep .03'" | tee color.txt


^^^ 只用tee也可以


printf "

first line
\e[32msecond\e[0m line
\e[33mthird\e[0m line
\e[35mfourth\e[0m line
\e[31mfifth\e[0m line
last line

" | perl -pe "system 'sleep .03'" | sed $'s,\x1b\[[0-9;]*[a-zA-Z],,g' | tee color.txt

^^^ 但当结合起来时,显然有缓冲作用。

这是什么原因造成的?如果有人可以解释一下吗?

已编辑:

当 sed 与 tee 交换时,它不再缓冲,但显然不是我想要的


printf "

first line
\e[32msecond\e[0m line
\e[33mthird\e[0m line
\e[35mfourth\e[0m line
\e[31mfifth\e[0m line
last line

" | perl -pe "system 'sleep .03'"  | tee color.txt | sed $'s,\x1b\[[0-9;]*[a-zA-Z],,g'

所有这些在以下情况下的行为完全相同:

stdout 通常仅在连接到终端时才进行行缓冲。将它连接到管道会导致完全缓冲。

虽然一些命令,包括tee,保证根本不会缓冲(因此tee | sed的最后一个例子)。

您可以使用 stdbuf -oL sed 's...g'unbuffer sed 's...g' 来获得行缓冲。 stdbuf 是 GNU coreutils 的一部分,因此应该在 Linux 上可用,它在 FreeBSD 上也默认可用。

这篇 2006 年的文章很旧,但提供了一些很好的细节。作者是 GNU coreutils 维护者。

http://www.pixelbeat.org/programming/stdio_buffering/