为什么“grep -q”会消耗整个输入文件?

don*_*sti 23 grep

考虑以下输入文件:

1
2
3
4
Run Code Online (Sandbox Code Playgroud)

跑步

{ grep -q 2; cat; } < infile
Run Code Online (Sandbox Code Playgroud)

不打印任何东西。我希望它打印

3
4
Run Code Online (Sandbox Code Playgroud)

如果我将其更改为,我可以获得预期的输出

{ sed -n 2q; cat; } < infile
Run Code Online (Sandbox Code Playgroud)

为什么第一个命令不打印预期的输出?
这是一个可搜索的输入文件,并且符合OPTIONS下的标准

-q
      Quiet. Nothing shall be written to the standard output, regardless of 
      matching lines. Exit with zero status if an input line is selected.
Run Code Online (Sandbox Code Playgroud)

再往下,在应用程序用法下(强调我的):

-q选项提供了一种轻松确定模式(或字符串)是否存在于一组文件中的方法。在搜索多个文件时,它提供了性能改进(因为它可以在找到第一个匹配项后立即退出)[...]

现在,按照相同的标准(在Introduction 中,在INPUT FILES 下

当标准实用程序读取可查找的输入文件并在到达文件结尾之前无错误地终止时,该实用程序应确保打开文件描述中的文件偏移量正确定位在实用程序处理的最后一个字节之后[. ..]

tail -n +2 file
(sed -n 1q; cat) < file
...
Run Code Online (Sandbox Code Playgroud)

只有当文件可查找时,第二个命令才与第一个命令等效。


为什么要grep -q消耗整个文件?


这是gnu grep重要的(尽管Kusalananda刚刚确认在 OpenBSD 上也会发生同样的情况)

Ste*_*itt 37

grep 确实提前停止,但它会缓冲其输入,因此您的测试太短(是的,我意识到我的测试不完美,因为它不可搜索):

seq 1 10000 | (grep -q 2; cat)
Run Code Online (Sandbox Code Playgroud)

在我的系统上从 6776 开始。这与GNU grep 中默认使用的 32KiB 缓冲区匹配:

seq 1 6775 | wc
Run Code Online (Sandbox Code Playgroud)

产出

   6775    6775   32768
Run Code Online (Sandbox Code Playgroud)

请注意,POSIX 只提到了性能改进

搜索多个文件时

由于部分读取单个文件,这并没有为性能改进设定任何期望。