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'
所有这些在以下情况下的行为完全相同:
mac 与 zsh
mac 与 bash
docker 运行 -it ubuntu bash
docker 运行 -it ubuntu sh
$ sw_vers
ProductName: macOS
ProductVersion: 11.6
BuildVersion: 20G165
$ /bin/zsh --version
zsh 5.8 (x86_64-apple-darwin20.0)
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.
stdout 通常仅在连接到终端时才进行行缓冲。将它连接到管道会导致完全缓冲。
虽然一些命令,包括tee
,保证根本不会缓冲(因此tee | sed
的最后一个例子)。
您可以使用 stdbuf -oL sed 's...g'
或 unbuffer sed 's...g'
来获得行缓冲。 stdbuf
是 GNU coreutils 的一部分,因此应该在 Linux 上可用,它在 FreeBSD 上也默认可用。
这篇 2006 年的文章很旧,但提供了一些很好的细节。作者是 GNU coreutils 维护者。
任何人都可以帮助解释为什么单独使用时 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'
所有这些在以下情况下的行为完全相同:
mac 与 zsh
mac 与 bash
docker 运行 -it ubuntu bash
docker 运行 -it ubuntu sh
$ sw_vers ProductName: macOS ProductVersion: 11.6 BuildVersion: 20G165 $ /bin/zsh --version zsh 5.8 (x86_64-apple-darwin20.0) $ /bin/bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20) Copyright (C) 2007 Free Software Foundation, Inc.
stdout 通常仅在连接到终端时才进行行缓冲。将它连接到管道会导致完全缓冲。
虽然一些命令,包括tee
,保证根本不会缓冲(因此tee | sed
的最后一个例子)。
您可以使用 stdbuf -oL sed 's...g'
或 unbuffer sed 's...g'
来获得行缓冲。 stdbuf
是 GNU coreutils 的一部分,因此应该在 Linux 上可用,它在 FreeBSD 上也默认可用。
这篇 2006 年的文章很旧,但提供了一些很好的细节。作者是 GNU coreutils 维护者。