2012-04-03 51 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

相關問題