为什么我的“grep”停止过滤它认为是“二进制”的非 ASCII 文件?

为什么我的“grep”停止过滤它认为是“二进制”的非 ASCII 文件?

我正在使用一台 Windows-10 计算机,使用 WSL。

我正在调查由 C# 应用程序生成的日志文件NLog。我期望日志条目会出现在整个文件的各个位置,但我看到以下内容:

Linux prompt> grep "geen mengcontainer" logfile.log
2023-03-07 07:25:08.7971 | Warn | ... | geen mengcontainer.
2023-03-07 07:25:09.8285 | Warn | ... | geen mengcontainer.
2023-03-07 07:25:10.8754 | Warn | ... | geen mengcontainer.
Binary file logfile.log matches

如您所见,在 07:25:10 之后,grep停止了,尽管文件在当天的剩余时间内继续运行。似乎有一些字符表明grep该文件不是文本文件,而是二进制文件,导致grep停止工作。

有关该文件的更多信息:

Linux prompt>file logfile.log
logfile.log: ASCII text, with CRLF line terminators

有关我的 Linux WSL 安装的更多信息:

Linux prompt>uname -a
Linux ComputerName 4.4.0-19041-Microsoft
  #2311-Microsoft Tue Nov 08 17:09:00 PST 2022 
  x86_64 x86_64 x86_64 GNU/Linux

Linux prompt> cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
...
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

关于我的安装的更多信息grep

Linux prompt> grep --version
grep (GNU grep) 3.4

我能做些什么?

  • 有人知道如何查找和替换负责grep停止过滤的字符吗?
  • 有人知道我可以添加哪些额外的参数或开关grep以便不停止过滤吗?
  • 有人知道grep没有这种行为的版本吗?(请考虑到apt update在我的环境中它不起作用)

提前致谢

答案1

用于grep -a强制将文件始终视为文本。

“二进制文件”检测对代码页敏感 – 如果 grep 像在 Linux 上一样需要 UTF-8 输入,它实际上会将“ANSI”(Windows-125x、ISO 8859-x)编码的文本文件检测为二进制文件。在“C”语言环境中使用LC_CTYPE=C grep或运行 grepLC_ALL=C grep也可以避免此问题。

(此外,“文件”关于输入为“ASCII”的说法完全基于对文件内初始字节的快速查看;它实际上并没有扫描整个文件,而“grep”当然会扫描整个文件。)

通常整个文件都采用相同的编码(即所有文件都可能是非 UTF-8),因此查找有问题的字符的一个简单方法是搜索非 ASCII 字节(LC_ALL=C 可能被需要):

grep -a -P -n --color '[^\x00-\x7F]' logfile.log
perl -ne 'print "Line $.:\t$_" if /[^\0-\177]/' < logfile.log

这也将突出显示有问题的字节:

perl -ne 'print "Line $.:\t$_" if s/[^\0-\177]/sprintf"\e[41m<%02X>\e[m",ord$&/ge' < logfile.log

如果文件除了一些奇怪的行之外,有效的 UTF-8 编码,使用类似的方法打印 UTF-8 解码失败的行:

perl -MEncode -ne 'print "Line $.:\t$_" if !eval{decode("UTF-8", $_, Encode::FB_CROAK)}' < logfile.log

相关内容