为什么我用 grep -I 得到“二进制文件匹配”?

Rus*_*lan 5 grep binary

在下面的例子中,grep行为很奇怪:它提供了-I选项,根据手册页,它应该grep忽略二进制文件(类似于--binary-files=without-match),但我仍然得到“二进制文件匹配”输出。

$ cat <<'EOF' | uudecode > test-file
begin 664 /dev/stdout
M>`&5SLU*Q$`0!&#/>8J^"TM/=^8/1%2\>1`\>.^9Z=D-9!))9@7?WBB^@%"G
MHOBHO+8V=2!'-WU3A9PX%*8PBB:VGK@6)Y*HFAB(.2;.;$SQPX=LNG3(>2SH
MDJE!5;R+E9P21J::8U2+?@R>RK&7:[^L&[Q=]UD6>)$D?9<O_82[Y$\&S4_,
MP[G)-)_RVN[!6(S.>F0/M\B(P]$>5[O^%_$8+/(?,CSI+]%DD;/"^^,K3`OD
,6?8=GK6MPS?WDU!"
`
end
EOF
$ grep -I 8 test-file
Binary file test-file matches
$ grep --binary-files=without-match 8 test-file
Binary file test-file matches
Run Code Online (Sandbox Code Playgroud)

显然,grep考虑二进制文件,但仍然尝试匹配并报告结果。为什么没有像-I选项规定的那样忽略“二进制文件” ?

我在 Ubuntu 18.04 上使用 GNU grep 3.1。

mur*_*uru 8

查看grep 手册,这似乎是因为(我的粗体):

如果type是 ' without-match',当grep 发现空输入二进制数据时, 它假定文件的其余部分不匹配;这相当于-I选项。

但是,grep 也将其他数据视为表示二进制文件:

非文本字节表示二进制数据;这些是被不正确地编码当前区域任一输出字节(参见环境变量),或零输入字节时-z--null-data未给出)的选项(见其它选项)。

因此,如果出现以下情况,则不会打印消息:

  • 给出了-I/--binary-files=without-match选项
  • 二进制岬是由于空字节。

但是,示例输入并非如此。示例文件被视为二进制文件,因为它不适合当前语言环境(可能是某些 UTF 语言环境),而不是因为它具有空字节。除此以外:

% LC_ALL=C grep 8 test-file  
x???J?@`?y??
dIf??(??P??????6u G7}S??8?0?&???'????9&?lL?Çl?t?y,?AU????F??cT?~
                                                                 ???k??]?Yx?$}?/????O?O?ù?4?????X??zd????W???,?2<?/?d?????+L
                                                                                                                            ?Y?????7??PB
Run Code Online (Sandbox Code Playgroud)

如果我向文件中添加一个空字节,grep 将失败:

% printf '\0' >> test-file
% grep -I 8 test-file    
% echo $?
1
Run Code Online (Sandbox Code Playgroud)