【发布时间】:2010-08-22 07:33:32
【问题描述】:
$ cat weirdo
Lunch now?
$ cat weirdo | grep Lunch
$ vi weirdo
^@L^@u^@n^@c^@h^@ ^@n^@o^@w^@?^@
我有一些文件包含带有诸如^@ 之类的非打印字符的文本,这会导致我的greps 失败(如上所述)。
我怎样才能得到我的grep 工作?有什么方法不需要修改文件吗?
【问题讨论】:
$ cat weirdo
Lunch now?
$ cat weirdo | grep Lunch
$ vi weirdo
^@L^@u^@n^@c^@h^@ ^@n^@o^@w^@?^@
我有一些文件包含带有诸如^@ 之类的非打印字符的文本,这会导致我的greps 失败(如上所述)。
我怎样才能得到我的grep 工作?有什么方法不需要修改文件吗?
【问题讨论】:
您的文件似乎是用 UTF-16 编码的,而不是 8 位字符集。 '^@' 是 ASCII NUL '\0' 的表示法,通常会破坏字符串匹配。
对此进行无损处理的一种技术是使用过滤器将 UTF-16 转换为 UTF-8,然后在输出中使用 grep - 假设命令是“utf16-utf8”,你会写:
utf16-utf8 weirdo | grep Lunch
作为“utf16-utf8”的粗略近似,您可以考虑:
tr -d '\0' < weirdo | grep Lunch
这会从输入文件中删除 ASCII NUL 字符,并让grep 对“清理”输出进行操作。从理论上讲,它可能会给您带来误报;实际上,它可能不会。
【讨论】:
iconv 应该无处不在:iconv -f UTF-16 -t UTF-8 weirdo
iconv 比 utf16-utf8 的假设要少得多。当然,作为一个 shell 脚本,utf16-utf8 现在是一个微不足道的单行代码:exec iconv -f UTF-16 -t UTF-8 "$@"。
tr 命令就是为此而生的:
cat weirdo | tr -cd '[:print:]\r\n\t' | grep Lunch
【讨论】:
您可能会使用strings(1) 工具取得一些成功,例如:
strings file | grep Launch
更多详情请见man strings。
【讨论】:
strings 命令通常适用于超过特定阈值的可打印字符序列 - 默认情况下为 4。在显示的示例中,每个可打印的内容与下一个可打印内容由 NUL 分隔,因此字符串将找不到任何内容。我想strings -n 1(或某些版本中的-s 1)可能会解决问题……除了每个输出字符串通常用换行符与下一个字符串分隔。因此,您可能必须删除换行符,这也会以不同的方式使内容变得不可读(如果匹配,则始终打印整个文件)。
Strings v2.51 Copyright (C) 1999-2013 Mark Russinovich Sysinternals - www.sysinternals.com usage: strings [-a] [-f offset] [-b bytes] [-n length] [-o] [-q] [-s] [-u] <file or directory> -a Ascii-only search (Unicode and Ascii is default) -b Bytes of file to scan -f File offset at which to start scanning. -o Print offset in file string was located -n Minimum string length (default is 3) -q Quiet (no banner) -s Recurse subdirectories -u Unicode-only search (Unicode and Ascii is default)
你可以试试
awk '{gsub(/[^[:print:]]/,"") }1' file
【讨论】: