假设我在bash中有以下命令:
one | two
one
运行很长一段时间,产生一个输出流,two
对该流的每一行执行快速操作,但two
根本不起作用,除非它读取的第一个值告诉它每行要读取多少个值。one
不输出这个值,但我事先知道它是什么(假设它是15
)。我想在输出one
之前通过管道发送一个15n
。我不想修改one
或two
。
我的第一个想法是:
echo "$(echo 15; one)" | two
这给了我正确的输出,但在命令one
完成之前,它根本不会通过管道进行流式传输。我希望输出立即通过管道开始流式传输,因为执行需要很长时间(几个月)。
我也试过:
echo 15; one | two
当然,它会输出15,但不会通过管道将其发送到two
。
bash中是否有方法通过管道传递"15\n",然后开始通过同一管道流式传输one
的输出?
您只需要shell分组构造:
{ echo 15; one; } | two
大括号周围的空格和后面的分号是必需的。
测试:
one() { sleep 5; echo done; }
two() { while read line; do date "+%T - $line"; done; }
{ printf "%sn" 1 2 3; one; } | two
16:29:53 - 1
16:29:53 - 2
16:29:53 - 3
16:29:58 - done
使用命令分组:
{ echo 15; one; } | two
完成!
您可以使用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
然后,你应该能够像往常一样将其转换为"两个"。