如何安全地“组合”多个程序打印的行?

Vi.*_*Vi. 11 shell io-redirection

假设我想并行执行多个程序并将它们的输出合并到一个管道中:

sh -c '
    (echo qqq; echo qqq2; echo qqq3)&
    (echo www; echo www2; echo www3)& 
    (echo eee; echo eee2; echo eee3)& 
  wait; wait; wait'
Run Code Online (Sandbox Code Playgroud)

这种 shell 方法适用于这个简单的情况,但我希望如果程序以缓冲方式输出更多和更长的行,它会失败,像这样(构造):

qqq
qqwww
q2
qqq3www2

wwweee3

eee2
eee3
Run Code Online (Sandbox Code Playgroud)

我被暗示使用的解决方案之一是tail -f

tail -n +0 -q -f <(echo qqq; echo qqq2; echo qqq3) <(echo www; echo www2; echo www3) <(echo eee; echo eee2; echo eee3)
Run Code Online (Sandbox Code Playgroud)

,但这是次优选项:它输出数据缓慢,不会终止;在这种情况下,我看到的输出不是“睡眠”顺序,而是参数顺序:

tail -n +0 -q -f <(sleep 1; echo qqq; sleep 1; echo qqq2; echo qqq3) <(echo www; echo www2; sleep 10; echo www3) <(echo eee; sleep 4; echo eee2; echo eee3) | cat
Run Code Online (Sandbox Code Playgroud)

我为此实现了一个特殊的小程序,但相信应该有一些标准的好方法来做到这一点。

如何使用标准工具(并且没有tail -f缺点)做到这一点?

sta*_*xyz 0

我想不出任何简单的事情可以帮助你,如果你的行太长,一个程序将在它能够完成向标准输出写入一行之前被发送到睡眠状态。

但是,如果您的行足够短,可以在进程切换之前完全写入,并且您的问题是生成一行需要很长时间,则可以使用 read 缓冲输出。

例如:

((./script1 | while read line1; do echo $line1; done) & \
(./script2 | while read line2; do echo $line2; done)) | doSomethingWithOutput
Run Code Online (Sandbox Code Playgroud)