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

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

在下面的示例中,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

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

我在 Ubuntu 18.04 上使用 GNU grep 3.1。

答案1

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

如果类型那时候without-matchgrep 发现空输入二进制数据 它假设文件的其余部分不匹配;这相当于该-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

如果我向文件添加空字节,grep 会成功失败:

% printf '\0' >> test-file
% grep -I 8 test-file    
% echo $?
1

相关内容