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

时间:2012-04-03 06:47:41

标签: shell

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

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

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

11 个答案:

答案 0 :(得分:93)

grep -a

它不能比那简单。

答案 1 :(得分:89)

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

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

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

这会将任何小于空格字符(换行符除外)和大于126的任何内容更改为.字符,只保留printables。


如果您希望每个“非法”字符替换为不同的字符,您可以使用类似下面的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

答案 2 :(得分:64)

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

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

然后可以进一步后处理以移除垃圾;这与您使用tr执行任务的查询最相似。

答案 3 :(得分:33)

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

strings binary.file | grep foo

答案 4 :(得分:19)

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

grep --binary-files=text

您可能还想添加-o--only-matching),这样您就不会得到大量的二进制乱码,这会让您的终端感到烦恼。

答案 5 :(得分:16)

从Grep 2.21开始,二进制文件为treated differently

  

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

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

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

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

答案 6 :(得分:3)

正如詹姆斯·塞尔瓦库马已经说过的那样,grep -a可以解决问题。 -a或--text强制Grep将输入流作为文本处理。 请参阅管理页面http://unixhelp.ed.ac.uk/CGI/man-cgi?grep

cat test.log | grep -a somestring

答案 7 :(得分:3)

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

答案 8 :(得分:2)

你可以做到

strings test.log | grep -i

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

这是我在未安装“字符串”命令的系统中使用的

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

与“ cat -v文件名”不同,这需要打印后一键打印文本并删除不可打印的字符,后者需要进行一些后处理才能删除不需要的内容。请注意,某些二进制数据可能是可打印的,因此您仍然会在这些好东西之间得到一些混乱。我认为如果您可以使用字符串,也可以消除这种混乱。