2016-04-24 31 views
0

没想到,这失败(无输出;在SH的zsh庆典试过):为什么我不能通过管道多次过滤尾部的输出?

echo "foo\nplayed\nbar" > /tmp/t && tail -f /tmp/t | grep played | sed 's#pl#st#g'

需要注意的是两次的grep也失败了,这说明这是相当无关使用哪些命令:

# echo -e "foo\nplayed\nbar" > /tmp/t && tail -f /tmp/t | grep played | grep played 

grep的单独作品:

# echo -e "foo\nplayed\nbar" > /tmp/t && tail -f /tmp/t | grep played 
played 

sed的单独作品:

# echo -e "foo\nplayed\nbar" > /tmp/t && tail -f /tmp/t | sed 's#pl#st#g'` 
foo 
stayed 
bar 

随着代替,它的工作原理:

# echo -e "foo\nplayed\nbar" > /tmp/t && cat /tmp/t | grep played | sed 's#pl#st#g' 
stayed 

随着journalctl --follow,它就像tail一样失败。

什么是对暂时无法管两次的原因吗?

回答

1

这是一个缓冲的问题 - 第一grep的缓冲它的输出时,它的管道到另一个命令,但如果没有它打印到标准输出。有关更多信息,请参见http://mywiki.wooledge.org/BashFAQ/009

+0

谢谢,编。文章建议首先检查是否有可能被消除的不必要的命令。在我的特殊情况下,我能够做到这一点,加入'--silent'和显式打印替代行('p')。例如'sed --silent's#pl#st#p''。 (否则,提到的* unbuffered *变体将会是一条可行的路线。) – user569825

+0

我从来没有听说过'--silent',看起来像它和更常见的'-n'一样。这将打印包含“pl”的行,而不是“玩过”的想法。您可以使用sed执行'/ played/{s/pl/st/gp}'等操作,但请检查语法。在awk中它会是'awk'/播放/ {gsub(/ pl /,“st”); print}''。 –

+0

幸运的是,我的用例比我给出的例子更复杂。因此,在输出中实际需要接收替换的每一行。不过,对于未来的情况,我会对sed的正确语法感到好奇。 (Btw'--silent' *是*'-n'。我更喜欢在编写脚本和记录时使用精细的开关变体。) – user569825

相关问题