如何复制流并以流方式处理两个部分?

如何复制流并以流方式处理两个部分?

有时我想在管道中插入一些东西以用于报告或其他一些次要用途。它可能像 一样简单wc -l,或更复杂,比如awk甚至是 python 脚本。运行这样的管道会很好:

zcat my_data_file.gz \
| wc -l > /tmp/linecount
| process_data.py

问题是大多数实用程序不会将数据正确输出到标准输出。tee可以将数据写入临时文件,但是我必须等到一切完成:

zcat my_data_file.gz \
| tee /tmp/f \
| process_data.py && \
wc -l /tmp/f > /tmp/linecount && rm /tmp/f

这不是最佳的:它可能是一个运行时间非常长的管道;我可能希望wc更快地看到类似物的中间结果;我可能不想将所有数据存储在临时文件中。

答案1

您可以使用tee并处理替换>(...)

zcat my_data_file.gz |

# Count number of lines in stream
tee >(wc -l > /tmp/linecount) |

# Further processing
process_data.py

请注意,管道可用于行延续,并且注释可以散布在命令之间,这是构建复杂管道时的一个很好的功能。

答案2

它并不完全有效,但你可以通过以下方式实现这一点命名管道,您可以使用它来创建mkififo(1)

对于问题中的例子:

mkfifo /tmp/f

wc -l /tmp/f > /tmp/linecount &

zcat my_data_file.gz \
| tee /tmp/f \
| process_data.py &

wait

rm /tmp/f

注意&附加在wc和 管道上的;这意味着 shell 会将任务推送到后台。然后,调用将wait等待所有后台任务完成。这两个过程将大约在同一时间完成。

请注意,如果您的某个进程速度明显较慢,则可能会显着减慢整个进程的速度,因为tee可能会阻塞其标准输出管道或正在写入的命名管道。编辑:此外,它现在有更多的故障模式,因为如果辅助进程失败,tee 将因管道损坏而退出。

相关内容