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

Dan*_*Lin 116 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
Run Code Online (Sandbox Code Playgroud)

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

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

Jam*_*mar 100

grep -a
Run Code Online (Sandbox Code Playgroud)

它不能比这更简单.

  • 这与[paxdiablo](http://stackoverflow.com/a/9988534/829755)2年前提到的`grep --text`相同 (3认同)
  • 是的,除了除非您执行以下操作,否则这在OSX上将不起作用:`LC_ALL =“ C” grep -a` (2认同)

pax*_*blo 90

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

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

tr '[\000-\011\013-\037\177-\377]' '.' <test.log | grep whatever
Run Code Online (Sandbox Code Playgroud)

这会将任何小于空格字符(换行符除外)和任何大于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;
}
Run Code Online (Sandbox Code Playgroud)

这将给你{{NN}},NN角色的十六进制代码在哪里.您可以简单地调整所需printf的任何输出样式.

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

pax$ printf 'Hello,\tBob\nGoodbye, Bob\n' | ./filterProg
Hello,{{09}}Bob
Goodbye, Bob
Run Code Online (Sandbox Code Playgroud)

  • `````grep --text````为我做了伎俩.谢谢. (3认同)
  • 经过测试,`tr'[\ 000- \ 010 \ 013 \ 014 \ 016- \ 037 \ 177- \ 377]''_'可行,cntrl不适合我的情况。 (2认同)
  • 您可以通过将`grep --text`连接到`tr`来保存`cat`步骤,而不是相反.这也允许您grep多个文件并在输出中保留文件名引用. (2认同)

vie*_*tti 66

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

$ cat -v tmp/test.log | grep re
line1 re ^@^M
line3 re^M
Run Code Online (Sandbox Code Playgroud)

然后可以进一步后处理以删除垃圾; 这与您关于使用tr任务的查询最相似.

  • 解决了我的问题.谢谢!这是什么`man cat`所说的`-v`:`-v, - show-nonprinting``use ^和M-notation,LFD和TAB除外 (5认同)

moo*_*ody 33

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

strings binary.file | grep foo
Run Code Online (Sandbox Code Playgroud)

  • 我很欣赏@paxdiablo的回答,但是为了快速回答并继续工作,你不能错过这个. (2认同)

A B*_*A B 19

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

grep --binary-files=text
Run Code Online (Sandbox Code Playgroud)

你可能还想添加-o(--only-matching),这样你就不会得到大量的二进制乱码,这会使你的终端烦恼.


小智 16

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

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

那么现在发生的是,对于二进制数据,所有非文本字节(包括换行符)都被视为行终止符.如果要更改此行为,您可以:

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

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


Kev*_*chs 9

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