我在使用 grep 过滤 make 输出时遇到了问题。特别是,
make target 2>&1 | grep -E --color=never "^make.*"
按预期工作,但以下内容不会在控制台上打印任何输出:
make target 2>&1 | grep -E --color=never "^make.*" | cat
我是不是忽略了某些显而易见的东西?为什么第一个命令输出,而第二个命令不输出?这与某种 IO 缓冲有关吗?还是我只是太笨了?
[编辑]: cat
只是我想要使用的实际命令的最小测试用例占位符。
[编辑]:这似乎不是 grep 的问题,因为用确认导致相同的行为。
[编辑]:以 cat 为占位符的脚本:
#!/bin/bash
cat - \
| grep -E --color=never "^.*warning:.*|^.*error:.*|^make.*[Ee]rror.*|^make.*" \
| hilite.sh -r "^.*warning:.*" -f yellow -B \
| hilite.sh -r "^.*error:.*" -f red -B \
| hilite.sh -r "^make.*[Ee]rror.*" -f red -B \
| hilite.sh -r "^make.*" -f magenta
[编辑]:我认为这是一个缓冲/IO 问题。我将让构建运行一段时间,看看它最终是否能将输出放到需要的地方!
答案1
可能是grep
检测到它没有写入 TTY,因此它会缓冲更多输出,而不是以通常的行缓冲模式运行(即,您会看到找到的每一行)。此行为效率更高,因为它会减少write()
系统调用,但如果您是等待流水线输出的用户,那么它可能有点误导。
如果您使用的是 GNU grep
(根据您的 Linux 标签,我假设您使用的是 GNU),请查看该--line-buffered
选项,它将强制grep
以更熟悉的行缓冲模式工作。从技术上讲,这可能会降低性能grep
(如手册页中所述),但由于您正在查看实时构建的输出,我怀疑它在这方面不会产生任何影响。
答案2
不确定你的命令应该做什么,对文件名中包含 make.* 的任何文件进行 cat 吗?
尝试改变cat
?xargs cat
答案3
您可以尝试尝试unbuffer
,例如,
make target 2>&1 | unbuffer -p grep -E --color=never "^make.*" | cat