我能够成功运行此命令:
tail -f my_file.txt | grep foo
它只显示带有字符串 的行foo
,并且一直显示它们。
但是当我运行这个命令时:
tail -f my_file.txt | grep foo | grep bar
它不显示任何行,即使有些行同时包含foo
和bar
。
我知道有一个在一次grep
调用中使用多种模式的解决方案,但我想知道为什么这条线失败了。
答案1
这是因为 C 运行时库的默认行为是缓冲对 stdout 的写入,直到写入完整的数据块(通常是几千字节),除非 stdout 连接到终端。
一旦中间的 grep 打印了一个完整的块,您就会得到输出,但是您必须再次等待下一个块填充,依此类推。这是对吞吐量的优化,当左侧命令只执行某些任务并终止而不是等待某些操作时,效果会更好。
GNU grep 可以--line-buffered
选择关闭该缓冲,因此这应该可以更好地工作:
tail -f my_file.txt | grep --line-buffered foo | grep bar
最后一个grep
打印到终端,因此默认情况下它是行缓冲的,不需要选项。
看 关闭管道中的缓冲缓冲问题的通用解决方案。
在这个有两个 grep 的特殊情况下,您可以使用单个 AWK 来代替,如 Stéphane Chazelas 在评论中提到的那样:
tail -f my_file.txt | awk '/foo/ && /bar/'
(顺便说一句,你也可以做类似的事情awk '/foo/ && !/bar/'
,用foo
但没有 来捕捉线条bar
。)
在 grep 中做同样的事情会更困难,因为grep -e foo -e bar
匹配包含以下内容的任何行任何一个 foo
或者 bar
。你需要类似的东西
... | grep -E -e 'foo.*bar|bar.*foo'
反而。
答案2
从布尔的角度来看,你似乎在期待富或者酒吧与你的 grep ,但从你所做的方式来看,你应该期望富和酒吧-- 唯一会被 grep 的行酒吧是那些通过了富首先是 grep 。
如果您希望 foo/bar 在标准输出上弹出,您需要使用:
尾-f my_file.txt | grep“foo|bar”
您可以添加任意多个关键字“pretty|much|like|这些”,只是不要忘记引号。 (或使用多个\|未加引号的\|术语)
第二点:因为它是尾部-f(如下)your_file.txt 也可能在特定时间没有附加包含两个关键字的行,通常最好剪切已知具有您期望的内容的该文件的共享:
tail -n 500 my_file.txt > my_sample.txt
从那里您可以尝试使用已知文本进行任何您喜欢的 grep 操作。 (我猜最后 500 行就足够了,根据需要进行调整。)