$ cat weirdo
Lunch now?
$ cat weirdo | grep Lunch
$ vi weirdo
^@L^@u^@n^@c^@h^@ ^@n^@o^@w^@?^@
我有一些包含非打印字符(如^@
)的文本文件,这会导致我的grep
命令失败(如上所述)。
我该如何让grep
命令正常工作?是否有不需要更改文件的方法?
看起来你的文件采用的是UTF-16编码而非8位字符集。'^@'是ASCII NUL '\0'的表示方法,这通常会破坏字符串匹配。
处理此类情况的一种无损技术是使用过滤器将UTF-16转换为UTF-8,然后在输出上使用grep
命令。假设命令为 'utf16-utf8',则可以写成:
utf16-utf8 weirdo | grep Lunch
tr -d '\0' < weirdo | grep Lunch
这将从输入文件中删除ASCII NUL字符,并让grep
在“清理后”的输出上操作。理论上,它可能会给出误报;实际上,它可能不会。
cat weirdo | tr -cd '[:print:]\r\n\t' | grep Lunch
您可以尝试使用strings(1)
工具,就像这样:
strings file | grep Launch
请参阅man strings
以获取更多详细信息。
strings
命令通常用于处理一定阈值(默认为 4)以上的可打印字符序列。在所示例子中,每个可打印字符都由 NUL 分隔开,因此 strings
找不到任何内容。我猜想 strings -n 1
(或某些版本中的 -s 1
)可能会解决这个问题……但是每个输出字符串通常都由换行符分隔。因此,您可能需要删除换行符,这也以另一种方式使得内容不可读(如果匹配,则整个文件始终被打印)。 - Jonathan LefflerStrings v2.51版权所有(C)1999-2013 Mark Russinovich Sysinternals - www.sysinternals.com 用法:strings [-a] [-f 偏移量] [-b 字节] [-n 长度] [-o] [-q] [-s] [-u] <文件或目录> -a 仅搜索Ascii码(默认为Unicode和Ascii) -b 要扫描的文件字节数 -f 开始扫描的文件偏移量 -o 打印在文件中找到的字符串偏移量 -n 最小字符串长度(默认为3) -q 安静模式(无标语) -s 递归子目录 -u 仅搜索Unicode(默认为Unicode和Ascii)
- Sunawk '{gsub(/[^[:print:]]/,"") }1' file
iconv
应该在任何地方都可用:iconv -f UTF-16 -t UTF-8 weirdo
- DarkDusticonv
比utf16-utf8
更为实用。当然,作为一个 shell 脚本,utf16-utf8
现在只需要一行代码:exec iconv -f UTF-16 -t UTF-8 "$@"
。 - Jonathan Leffler