我得到了我的应用程序日志,其中包含一个包含奇怪字符的字段。
我只有在使用less
命令时才能看到这些字符。
我试图将代码行的结果复制到文本文件中,然后看到
CTP_OUT=^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
我想知道是否可以找到这些空字符。我尝试使用grep
命令,但未显示任何内容
答案 0 :(得分:2)
我简直不敢相信,我可能会写一个涉及cat
的答案!
您正在观察的字符是不可打印的字符,通常用Carret notation书写。字符的插入符号是一种可视化不可打印字符的方法。如OP中所述,^@
是NULL
的表示。
如果文件中包含不可打印的字符,则可以使用cat -vET
将其可视化:
-E, --show-ends
:在每行末尾显示$
-T, --show-tabs
:将TAB
字符显示为^I
-v, --show-nonprinting
:使用^
和M-
表示法,除了LFD
和TAB
来源:
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{...}
指定任意数量的十六进制数字。
一个例子:
$ 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
的空值。