grep命令的管道符与tail命令无法配合使用?

4

我正在尝试通过查看日志来调试一个场景,这是我的命令

tail -f eclipse.log | grep 'enimation' | grep  -i 'tap'

基本上我所尝试的是筛选出所有带有动画效果的行,再从所有动画中找到包含"tap"的动画。
以下是返回空结果的样本数据。
*******enimation error*********TapExpand
*******enimation error*********TapShrink

这里返回了空结果。
如果我运行以下命令:
 tail -f eclipse.log | grep  -i 'enimation.*tap'

它返回正确的结果。有人能解释一下上述两个命令之间的区别以及为什么结果存在差异吗?它们在我看来都是相同的。


这绝对是那个问题的重复。但我认为来自一个略有不同的问题的答案实际上更好地解释了这个问题。 - Reinstate Monica Please
4个回答

7

grep正在缓冲其输出。要告诉GNU grep逐行输出输出,您需要在grep中使用--line-buffered选项使其工作:

tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'

根据man grep的说明:
--line-buffered
    Force output to be line buffered.  By default, output is line buffered when standard
    output is a terminal and block buffered otherwise.

3

grep 的输出不是终端,因此它使用块缓冲而不是行缓冲。您需要使用 --line-buffered 选项来强制行缓冲。

tail -f eclipse.log | grep --line-buffered 'enimation' | grep  -i 'tap'

对于其他不提供此选项的命令,您可以使用 stdbuf 命令强制进行行缓冲,例如:

tail -f eclipse.log | stdbuf -o1 grep 'enimation' | grep  -i 'tap'

1

你的输出被缓冲了。尝试:

tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'

3
抱歉,我看到我不是第一个在这里。 - Raul Andres

-2

尝试在grep命令中添加-E选项。很多反向引用特性没有它是无法工作的。我通常把它称为“是的,我确实知道我在做什么”的选项。


-1 完全是一个转移话题。问题中没有扩展的正则表达式特性。 - tripleee
-E选项是--extended-regexp的简写形式。来自man: 将PATTERN解释为扩展的正则表达式。在这种情况下,PATTERN是'enimation',无论是否解释为extended-regexp,它都不会改变。 - whoan
如果我们想通过模式enimation和tap过滤,那么-E选项可能会有所帮助,但如果我们想要首先过滤enimation然后再过滤tap(如果tap在行中的任何位置),则不适用。实现第一种情况的正确方法是tail -f eclipse.log | grep -iE "enimation|tap"或者tail -f eclipse.log | grep -iE "enimation.*tap",如果我们确定了顺序(tap始终在enimation之后),所有这些都是为了防止关于--line-buffered选项的性能问题。 - MediaVince

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接