我能够成功运行此命令:
tail -f my_file.txt | grep foo
它只显示带有 string 的行foo
,并且一直显示它们。
但是当我运行这个命令时:
tail -f my_file.txt | grep foo | grep bar
它不显示任何行,即使有些行同时包含foo
和bar
。
我知道有一个在单个grep
调用中使用多个模式的解决方案,但我想知道为什么这条线失败了。
我能够成功运行此命令:
tail -f my_file.txt | grep foo
它只显示带有 string 的行foo
,并且一直显示它们。
但是当我运行这个命令时:
tail -f my_file.txt | grep foo | grep bar
它不显示任何行,即使有些行同时包含foo
和bar
。
我知道有一个在单个grep
调用中使用多个模式的解决方案,但我想知道为什么这条线失败了。
这是因为 C 运行时库的默认行为是缓冲对 stdout 的写入,直到写入完整的数据块(通常是几千字节),除非 stdout 连接到终端。
一旦中间的 grep 打印了一个完整的块,您就会得到输出,但是您必须再次等待下一个块的填充,依此类推。这是对吞吐量的优化,当左侧命令只执行某些任务并终止而不是等待某些内容时,它的效果会更好。
GNU grep 可以
--line-buffered
选择关闭缓冲,所以这应该会更好:最后
grep
打印到终端,因此默认情况下它是行缓冲的,不需要选项。有关缓冲问题的通用解决方案,请参阅 关闭管道中的缓冲。
在这个有两个 grep 的特殊情况下,您可以使用例如单个 AWK,而不是评论中提到的 Stéphane Chazelas:
(顺便说一句,你也可以做一些事情,比如
awk '/foo/ && !/bar/'
, catching lines withfoo
but nobar
.)在 grep 中做同样的事情会更难,因为
grep -e foo -e bar
匹配任何包含orfoo
的bar
行。你需要类似的东西反而。
从布尔的角度来看,您似乎期待foo OR bar与您的 grep,但从您的方式来看,您应该期待foo AND bar——唯一会被 grep for bar 的行是那些通过foo grep的行首先。
如果你想在 stdout 上弹出 foo/bar,你需要使用:
您可以添加尽可能多的关键字“漂亮|多|喜欢|这些”,只是不要忘记引号。(或使用多个\|不带引号的\|术语)
第二个注意事项:由于它是tail -f(跟随)它也可能发生 your_file.txt 在那个非常特定的时间没有附加包含这两个关键字的行,通常最好削减该文件的一部分已知具有您所期望的:
从那里你可以用已知的文本尝试任何你喜欢的 grep。(我猜最后 500 行就足够了,根据需要进行调整。)