如何grep包含一些二进制数据的文本文件?

grep返回

二进制文件test.log匹配

例如

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 

我希望结果会显示line1和line3(共两行)。

是否可以使用tr将不可打印的数据转换为可读的数据,让grep再次工作?

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

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

然后可以进一步后处理去除垃圾; 这与你使用tr进行任务的查询最类似。

一种方法是简单地把二进制文件作为文本,用grep --text但是这可能会导致二进制信息被发送到你的terminal。 如果你运行一个解释输出stream的terminal(如VT / DEC或其他许多terminal),那么这不是一个好主意。

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

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

这将改变任何比空格字符(除了换行符)和任何大于126的东西都变成一个. 字符,只留下printables。


如果你想让每个“非法”字符replace为不同的字符,你可以使用类似下面的C程序,一个经典的标准inputfilter:

 #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是字符的hex代码。 您可以简单地调整printf以获得所需的任何样式的输出。

你可以看到这个程序在这里的行动,它在哪里:

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

它不能简单得多。

例如,您可以使用“string”从二进制文件中提取string

 strings binary.file | grep foo 

您可以强制grep查看二进制文件:

 grep --binary-files=text 

你可能还想添加-o (– --only-matching ),这样你就不会得到大量的二进制乱码,这将会使你的terminal变得困难。

从Grep 2.21开始,二进制文件的处理方式不同 :

当search二进制数据时,grep现在可以将非文本字节视为行终止符。 这可以显着提升性能。

那么现在发生的事情是,对于二进制数据,所有非文本字节(包括换行符)被视为行终止符。 如果你想改变这种行为,你可以:

  • 使用--text 。 这将确保只有换行符是行终止符

  • 使用--null-data 。 这将确保只有空字节是行终止符

正如詹姆斯·塞尔瓦库马尔(James Selvakumar)已经说过的那样, grep -a做到。 -a或–text强制Grep将inputstream作为文本处理。 见手册http://unixhelp.ed.ac.uk/CGI/man-cgi?grep

尝试

 cat test.log | grep -a somestring 

你可以做

 strings test.log | grep -i 

这将转换为可读的string输出到grep。

grep -a将强制grep从grep认为是二进制文件search并输出。 grep -a re test.log

您也可以尝试Word Extractor工具。 Word Extractor可以与计算机中的任何文件一起使用,以将包含人类文本/文字的string与二进制代码(exe应用程序,DLL)分离。