如何抓取一个文本文件,其中包含一些二进制数据?

Grep 返回

Binary file test.log matches

比如说

echo    "line1 re \x00\r\nline2\r\nline3 re\r\n" > test.log  # in zsh
echo -e "line1 re \x00\r\nline2\r\nline3 re\r\n" > test.log  # in bash
grep re test.log

我希望结果显示 line 1和 line 3(总共两行)。

有没有可能使用 tr将不可打印的数据转换成可读的数据,让 grep 再次工作?

141562 次浏览

例如,可以使用“字符串”从二进制文件中提取字符串

strings binary.file | grep foo

您可以使用以下命令强制 grep 查看二进制文件:

grep --binary-files=text

您可能还需要添加 -o(--only-matching) ,这样您就不会得到大量会阻塞终端的二进制胡言乱语。

一种方法是使用 grep --text将二进制文件简单地视为文本,但这很可能导致将二进制信息发送到您的终端。如果您运行的终端解释输出流(例如 VT/DEC 或许多其他终端) ,那么这确实不是一个好主意。

或者,您可以使用以下命令通过 tr发送您的文件:

tr '[\000-\011\013-\037\177-\377]' '.' <test.log | grep whatever

这将把任何小于空格字符(除了换行符)和大于126的字符更改为 .字符,只留下可打印字符。


如果你想用不同的字符替换每个“非法”字符,你可以使用下面的 C 程序,一个经典的标准输入过滤器:

#include<stdio.h>
int main (void) {
int ch;
while ((ch = getchar()) != EOF) {
if ((ch == '\n') || ((ch >= ' ') && (ch <= '~'))) {
putchar (ch);
} else {
printf ("\{\{%02x}}", ch);
}
}
return 0;
}

这将得到 \{\{NN}},其中 NN是字符的十六进制代码。您可以简单地调整 printf以获得任何您想要的输出样式。

你可以在这里看到这个程序的运行情况:

pax$ printf 'Hello,\tBob\nGoodbye, Bob\n' | ./filterProg
Hello,\{\{09}}Bob
Goodbye, Bob

从 Grep 2.21开始,二进制文件是 被区别对待:

在搜索二进制数据时,grep 现在可以将非文本字节视为行 这可以显著提高性能。

所以现在发生的是,对于二进制数据,所有非文本字节 (包括换行符)被视为行终止符 行为,你可以:

  • 这将确保只有换行符是行终止符

  • 这将确保只有空字节是行终止符

你可以的

strings test.log | grep -i

这将把 give 输出作为可读字符串转换为 grep。

您也可以尝试 文字提取器工具。字提取器可用于计算机中的任何文件,从二进制代码(exe 应用程序、 DLL)中分离包含人工文本/字的字符串。

grep -a

没有比这更简单的了。

正如 James Selvakumar 已经说过的,grep -a可以解决这个问题。-a 或—— text 强制 Grep 将输入流作为文本处理。 参见 Manpage < a href = “ http://unixhelp. ed.ac.uk/CGI/man-cgi? grep”rel = “ nofollow”> http://unixhelp.ed.ac.uk/cgi/man-cgi?grep

试试看

cat test.log | grep -a somestring

您可以通过 cat -v运行数据文件,例如

$ cat -v tmp/test.log | grep re
line1 re ^@^M
line3 re^M

然后可以进一步后期处理以删除垃圾; 这非常类似于关于使用 tr执行任务的查询。

-v只是告诉 cat显示非打印字符。

Grep-a 将强制 grep 搜索并输出 grep 认为是二进制的文件。 Grep-a re test.log

下面是我在一个没有安装“字符串”命令的系统中使用的方法

cat yourfilename | tr -cd "[:print:]"

与“ cat-v filename”不同的是,这种方法可以一下子打印文本并删除不可打印的字符,而“ cat-v filename”需要一些后处理来删除不需要的内容。注意,一些二进制数据可能是可打印的,所以你仍然会得到一些好东西之间的胡言乱语。我认为字符串也可以删除这些废话,如果你可以使用它们的话。