grep输出缓冲的判定条件及中间管道进程影响的原因探究
grep输出缓冲的决定因素及场景差异解析
核心机制:缓冲策略由输入输出类型决定
绝大多数类UNIX工具(包括grep、sed)的缓冲行为由标准stdio库控制,核心规则是:
- 当输入/输出连接到终端(TTY)时,使用行缓冲:遇到换行符就立刻刷新输出缓冲区。
- 当输入/输出连接到管道、文件等非终端设备时,使用全缓冲:默认攒够固定大小的缓冲区(通常4KB)才刷新,或者遇到EOF时强制刷新。
逐个场景拆解
echo XXX | grep XXX立即输出的原因
echo输出XXX\n后会立刻发送EOF给grep,grep收到EOF后会强制刷新缓冲区,不管缓冲区有没有满,所以你能马上看到匹配结果。带sed的命令需要凑够4KB才输出的原因
命令:cat <(yes 'a' | head -c 4090) /dev/stdin > /dev/stdout | sed ';' | grep XXX- 中间的
sed ';'是关键:sed的输出连接到管道(非终端),所以sed用全缓冲模式。 - 前面的
yes 'a' | head -c 4090已经输出了4090字节,你输入XXX\n又加了4字节,总共4094字节——还差2字节才到4KB的缓冲区大小,所以sed不会把数据传给grep。 - 只有当你再输入2字节,总数据量达到4096字节时,sed才会刷新缓冲区,把所有数据传给grep,grep匹配到
XXX后才输出。
- 中间的
去掉sed后立即输出的原因
命令:cat <(yes 'a' | head -c 4090) /dev/stdin > /dev/stdout | grep XXX- 这里没有sed这个中间缓冲层:cat会把4090个a加上你输入的
XXX\n立刻写入管道,grep能直接读到这些数据。 - 虽然grep的输入是管道(全缓冲模式),但GNU grep有个实用优化:当在全缓冲模式下读取到匹配内容时,会立即输出匹配行,而不会等缓冲区满——所以你输入
XXX\n后,grep扫描到匹配的行,马上就输出了。
- 这里没有sed这个中间缓冲层:cat会把4090个a加上你输入的
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

