2012-04-03 108 views
96

grep的返回如何用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 

祝结果将显示第1行和第3行(总共两个线)。

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

+0

请注意,有一种程序可以从二进制文件中滤除二进制字符,并只保留文本字符(可读)。这里: http://www.soft.tahionic.com/download-words_extractor/index.html – Ampere 2013-05-29 09:01:10

+0

不好意思,但是......你不是在'echo'命令中缺少'-e'吗? – 2014-12-13 00:46:34

+0

如果你使用'zsh',没有-e就没问题。如果你使用'bash',你应该添加'-e'。 – 2014-12-14 03:30:43

回答

50

您可以通过cat -v运行数据文件,e.g

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

这可能是再进一步处理后,除去垃圾;这与您对任务使用tr的查询最类似。

+2

解决了我的问题。谢谢!下面是'man cat'关于'-v'所说的:'-v,--show-nonprinting''使用^和M-表示法,除了LFD和TAB' – 2016-01-03 17:06:13

+0

请注意,这也适用于流水线。例如。 'set | cat -v | grep变量' – funroll 2016-09-28 20:01:56

+0

为什么使用这个if grep --text起作用?这似乎要复杂得多。 – 2017-03-02 14:57:30

32

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

strings binary.file | grep foo 
+1

分裂我的原始线 – 2012-04-03 07:02:40

+0

工作对我来说很好,因为来源是一个在每行上用UID调试日志。谢谢。 – mbrownnyc 2013-08-06 19:44:58

+0

也适合我。感谢您的回答。保存我的一天:) – Shekhar 2014-01-09 08:20:46

18

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

grep --binary-files=text 

您可能还需要添加-o--only-matching),这样你就不会得到吨二进制乱码即会博克你的终端。

+0

可能会输出二进制垃圾,如果输出是终端,并且终端驱动程序将其中的一部分解释为命令,可能会产生令人讨厌的副作用。 – 2012-04-03 07:02:16

+0

如果您使用'--only-matching',并且您的正则表达式与任意二进制数据不匹配,则不会有问题。 – alberge 2012-04-03 07:08:15

+0

如果正则表达式为'first。* end'且二进制数据包含'。*'模式,则无法为我的后处理修正过程。不管怎样,谢谢。 – 2012-04-03 08:00:35

77

一种方法是简单地把二进制文件为文本,无论如何,与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 
+0

此方法将所有二进制字符映射为相同的'。'符号。有其他方法将它们映射到可读的符号吗? – 2012-04-03 07:05:07

+0

当然,你可以通过一个不同的过滤器程序运行它,其中一个我在更新中提供。 – paxdiablo 2012-04-03 07:15:39

+1

我觉得'tr'[:cntrl:]'。''比较好。在你的tr语法中它应该是'\ 000- \ 010 \ 013 \ 014 \ 016- \ 037 \ 177- \ 377''。 – 2012-04-03 07:58:27

10

使用grep 2.21开始,二进制文件是treated differently

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

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

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

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

+0

是的,一个解决方法修复程序是expor LC_ALL = C && grep – netawater 2015-08-17 02:45:08

2

你可以做

strings test.log | grep -i 

这将转化给输出作为一个可读的字符串到grep。

0

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

+0

我的情况,我不需要单词提取器,我需要保留行号。 – 2013-06-01 06:20:16

68
grep -a 

它不能变得比这更简单。

+1

这对我来说非常适合! – 2015-09-28 01:59:56

+2

这和'grep --text'是一样的[paxdiablo](http://stackoverflow.com/a/9988534/829755)早在2年前提过 – user829755 2017-01-16 13:59:50

1

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

相关问题