查找具有非打印字符(空字节)的文件

时间:2019-01-10 14:49:30

标签: linux bash unix grep

我得到了我的应用程序日志,其中包含一个包含奇怪字符的字段。 我只有在使用less命令时才能看到这些字符。

我试图将代码行的结果复制到文本文件中,然后看到

CTP_OUT=^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@

我想知道是否可以找到这些空字符。我尝试使用grep命令,但未显示任何内容

2 个答案:

答案 0 :(得分:2)

我简直不敢相信,我可能会写一个涉及cat的答案!

您正在观察的字符是不可打印的字符,通常用Carret notation书写。字符的插入符号是一种可视化不可打印字符的方法。如OP中所述,^@NULL的表示。

如果文件中包含不可打印的字符,则可以使用cat -vET将其可视化:

  

-E, --show-ends :在每行末尾显示$
    -T, --show-tabs :将TAB字符显示为^I
    -v, --show-nonprinting :使用^M-表示法,除了LFDTAB

     

来源:man cat

我在其中添加了-E-T标志,以转换所有不可打印的内容。

由于grep不会以任何形式输出不可打印字符本身,因此您必须将其输出通过管道传递到cat才能看到它们。以下示例显示了所有包含不可打印字符的行

显示所有带有不可打印字符的行:

$ grep -E '[^[:print:]]' --color=never file | cat -vET

这里,ERE [^[:print:]]选择所有不可打印的字符。

显示所有带有NULL的行:

$ grep -Pa '\x00' --color=never file | cat -vET

请注意,我们需要在这里使用Perl正则表达式,因为它们了解十六进制和八进制表示法。

  

各种控制字符都可以用C语言样式编写:\n匹配换行符,\t制表符,\r回车符,\f换页等

     

更一般而言,\nnn(其中nnn是三个八进制数字的字符串)与本机代码点为nnn的字符匹配。如果您没有三位数字,您很容易遇到麻烦。因此,始终使用3,或者从Perl 5.14开始,您可以使用\o{...}指定任意数量的八进制数字。

     

类似地,\xnn(其中nn是十六进制数字)与本机序数为nn的字符匹配。同样,不完全使用两位数字是灾难的根源,但是您可以使用\x{...}指定任意数量的十六进制数字。

     

来源:Perl 5 version 26.1 documentation

一个例子:

$ printf 'foo\012\011\011bar\014\010\012foobar\012\011\000\013\000car\012\011\011\011\012' > test.txt
$ cat test.txt
foo
                bar

foobar

        car

如果我们现在单独使用grep,则会得到以下信息:

$ grep -Pa '\x00' --color=never test.txt

        car

但是将其管道输送到cat可以使我们可视化控制字符:

$ grep -Pa '\x00' --color=never test.txt | cat -vET
^I^@^K^@car$

为什么--color=never:如果您的grep调整为具有--color=auto--color=always,它将添加额外的控制字符,以将其解释为终端的颜色。这可能会使您对内容感到困惑。

$ grep -Pa '\x00' --color=always test.txt | cat -vET
^I^[[01;31m^[[K^@^[[m^[[K^K^[[01;31m^[[K^@^[[m^[[Kcar$

答案 1 :(得分:1)

sed可以。

 sed -n '/\x0/ { s/\x0/<NUL>/g; p}' file

-n跳过打印任何输出,除非明确要求。
/\x0/仅选择空字节的行。
{...}封装了多个命令,以便可以始终且仅在/\x0/在行中检测到空值时才集体应用它们。
s/\x0/<NUL>/g;用一个新的可见值替换空字节。您可以随心所欲地做它-我使用<NUL>既合理又明显,但不太可能发生。您可能应该先对其进行grep文件处理,以确保在使用该模式之前该模式不存在。
p;导致显示已编辑的行(因为它们具有空字节)。

这基本上使sed成为有效的grep的空值。