2

我遇到了如何使用 Unix(或 Windows)中的(最好是未命名的)管道将一个进程的标准输出发送到多个进程的答案?grep当我注意到一个奇怪的问题时,我正在玩弄。以下工作如我所料:

$ while [ 1 ]; do sleep 1 ; echo tick; done | tee >(grep -o ti) >(grep -o ic) >(grep tick) >/dev/null
ic
ti
tick
ic
tick
ti
^C

所有三个grep命令都应用于​​循环的输出。

但是,如果我将 的输出通过管道tee传输到 grep 中(而不是将其重定向到 /dev/null),grep则文件上的 s 将停止工作:

$ while [ 1 ]; do sleep 1 ; echo tick; done | tee >(grep -o ti) >(grep -o ic) | grep tick
tick
tick
^C

为什么会这样?

4

1 回答 1

3

我冒昧的猜测一下...

tee >(grep -o ti) >(grep -o ic) >(grep tick) >/dev/null
tee >(grep -o ti) >(grep -o ic) | grep tick

在第一个命令中,参数是从左到右处理的,因此grep -o ti它的输出将转到标准输出,其他两个进程替换也是如此,然后将标准输出tee重定向到/dev/null(但进程已经启动原始标准输出)。

在第二个命令中,grep tick在 shell 工作之前已经设置了管道,因此管道>(grep -o ti)的标准输出grep顺着管道传输。该命令不选择ti和行。如果您将其更改为,您可能也会看到and行。icgrep tickgrep itiic

我不得不将命令调整为:

while true; do echo tick; done |
tee >(grep -o ti) >(grep -o ic) | grep i | grep -v tick

查看tiandic命令。这与使用标准 I/O 进行缓冲有关;命令的输出grep将进入管道,因此它是完全缓冲的,并且输出分批出现。除非我放弃sleep 1,否则要花很长时间才能看到替代输出。

一个更好的查看输出的命令是:

while true; do echo tick; done |
tee >(grep -o ti) >(grep -o ic) | grep i | uniq

输出包含如下行:

ictick
tick
ic
i
ti
tick
ic
tick
ti
ttick
ic
itick
tick
ic
i
ti
tiic
ictick
tick

这个故事的寓意可能是确保每个流程替换的输出都转到一个已知文件。

于 2013-04-18T21:19:16.830 回答