5

假设我在 bash 中有以下命令:

one | two

one运行很长时间,产生一个输出流并two对该流的每一行执行快速操作,但two根本不起作用,除非它读取的第一个值告诉它每行要读取多少个值。one不输出该值,但我提前知道它是什么(假设它是15)。我想15\n在输出之前通过管道发送一个one。我不想修改onetwo

我的第一个想法是:

echo "$(echo 15; one)" | two

one这给了我正确的输出,但在命令完成之前它根本不会流过管道。我希望输出立即通过管道开始流式传输,因为执行需要很长时间(几个月)。

我也试过:

echo 15; one | two

当然,它会输出 15,但不会通过管道将其发送到two.

bash 中有没有办法通过管道传递 '15\n' 然后开始one通过同一管道流式传输输出?

4

3 回答 3

16

您只需要 shell 分组结构:

{ echo 15; one; } | two

大括号周围的空格和结尾的分号是必需的。

去测试:

one() { sleep 5; echo done; }
two() { while read line; do date "+%T - $line"; done; }
{ printf "%s\n" 1 2 3; one; } | two
16:29:53 - 1
16:29:53 - 2
16:29:53 - 3
16:29:58 - done
于 2013-06-28T20:30:48.990 回答
5

使用命令分组

{ echo 15; one; } | two

完毕!

于 2013-06-28T20:30:26.410 回答
2

你可以用 sed 做到这一点:

示例 'one' 脚本,每秒发出一行以显示它的行缓冲和运行。

#!/bin/bash
while [ 1 ]; do
    echo "TICK $(date)"
    sleep 1
done

然后通过此 sed 命令进行管道传输,请注意,对于您的特定示例,“ArbitraryText”将是字段数。我使用了 ArbitraryText,因此很明显这是插入的文本。在 OSX 上,-l不受 GNU Sed 的缓冲,我相信它是-u

 $ ./one | sed -l '1i\
> ArbitraryText
> '

它的作用是指示 sed 在处理文件的其余部分之前插入一行,其他所有内容都将原封不动地通过。

最终结果在没有块缓冲的情况下逐行处理(或者,等待输入脚本完成)

ArbitraryText
TICK Fri Jun 28 13:26:56 PDT 2013
...etc

然后,您应该能够像往常一样将其通过管道传输到“两个”中。

于 2013-06-28T20:28:54.250 回答