Grep 无法输出到管道?

bri*_*ice 3 linux unix bash shell command-line

我在对 make 输出进行 grep 过滤时遇到问题。特别是,

make target 2>&1 | grep -E --color=never "^make.*"
Run Code Online (Sandbox Code Playgroud)

按预期工作,但以下内容不会向控制台打印输出:

make target 2>&1 | grep -E --color=never "^make.*" | cat
Run Code Online (Sandbox Code Playgroud)

我错过了一些明显的东西吗?为什么第一个命令输出而不是第二个?是否与某种 IO 缓冲有关?还是我只是愚蠢?

[编辑]: cat只是我要使用的实际命令的最小测试用例占位符。

[编辑]:这似乎不是 grep 的问题,因为用ack替换它会导致相同的行为。

[编辑]: 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
Run Code Online (Sandbox Code Playgroud)

[编辑]:我认为这是一个缓冲/IO 问题。我让构建在 w/e 上运行,并将查看它是否最终在需要的地方获得输出!

Fat*_*ror 6

可能grep是检测到它没有写入 TTY,因此它缓冲了更多的输出,而不是在其通常的行缓冲模式下运行(即,您会看到找到的每一行)。这种行为更有效,因为它导致更少的write()系统调用,但如果您是等待流水线输出的用户,那么它可能有点误导。

如果您使用的是 GNU grep(并且基于您的 linux 标签,我假设您是),请查看该--line-buffered选项,该选项将强制grep在更熟悉的行缓冲模式下工作。从技术上讲,这可能会降低grep(如手册页中所述)的性能,但由于您正在查看实时构建的输出,我怀疑它会在这方面产生任何影响。