Grep 无法输出到管道?

Grep 无法输出到管道?

我在使用 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 吗?

尝试改变catxargs cat

答案3

您可以尝试尝试unbuffer,例如,

make target 2>&1 | unbuffer -p grep -E --color=never "^make.*" | cat

相关内容