【问题标题】:Why can't I filter tail's output multiple times through pipes?为什么我不能通过管道多次过滤tail的输出?
【发布时间】:2016-04-24 12:08:07
【问题描述】:

出乎意料,这失败了(无输出;在 shzshbash 中尝试过):

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

使用 cat 而不是 tail,它可以工作:

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

使用journalctl --follow,它就像使用tail 一样失败。

两次无法管道的原因是什么?

【问题讨论】:

标签: sed grep pipe tail


【解决方案1】:

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

【讨论】:

  • 谢谢,埃德。文章建议首先检查是否有可能消除的不必要的命令。在我的特殊情况下,我可以添加--silent 和显式打印替换行(p)。例如sed --silent 's#pl#st#p'。 (否则,上面提到的 unbuffered 变体将是可行的方法。)
  • 我从未听说过--silent,看起来它与更常见的-n 做同样的事情。这将打印包含pl 的行,而不是played 思想。您可以使用 sed 执行 /played/{s/pl/st/gp} 之类的操作,但请检查语法。在 awk 中是 awk '/played/{gsub(/pl/,"st");print}'
  • 幸运的是,我的用例比我给出的示例更复杂。因此,输出中实际上需要接收替换的每一行。不过,对于未来的情况,我会对 sed 的正确语法感到好奇。 (顺便说一句--silent -n。我只是更喜欢在编写脚本和记录时使用复杂的开关变体。)
猜你喜欢
  • 2014-09-21
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 2012-12-01
相关资源
最近更新 更多