从文件中删除非显示字符

3
$ cat weirdo 
Lunch now?
$ cat weirdo | grep Lunch
$ vi weirdo
  ^@L^@u^@n^@c^@h^@ ^@n^@o^@w^@?^@

我有一些包含非打印字符(如^@)的文本文件,这会导致我的grep命令失败(如上所述)。

我该如何让grep命令正常工作?是否有不需要更改文件的方法?

4个回答

6

看起来你的文件采用的是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在“清理后”的输出上操作。理论上,它可能会给出误报;实际上,它可能不会。


2
我不知道utf16-utf8,但是iconv应该在任何地方都可用:iconv -f UTF-16 -t UTF-8 weirdo - DarkDust
@DarkDust: 谢谢 - iconvutf16-utf8 更为实用。当然,作为一个 shell 脚本,utf16-utf8 现在只需要一行代码:exec iconv -f UTF-16 -t UTF-8 "$@" - Jonathan Leffler

5
命令就是为此而设计的:
cat weirdo | tr -cd '[:print:]\r\n\t' | grep Lunch

2

您可以尝试使用strings(1)工具,就像这样:

strings file | grep Launch

请参阅man strings以获取更多详细信息。


strings 命令通常用于处理一定阈值(默认为 4)以上的可打印字符序列。在所示例子中,每个可打印字符都由 NUL 分隔开,因此 strings 找不到任何内容。我猜想 strings -n 1(或某些版本中的 -s 1)可能会解决这个问题……但是每个输出字符串通常都由换行符分隔。因此,您可能需要删除换行符,这也以另一种方式使得内容不可读(如果匹配,则整个文件始终被打印)。 - Jonathan Leffler
Sysinternals具有字符串功能,可以显示可打印字符:Strings 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) - Sun

2
你可以尝试一下。
awk '{gsub(/[^[:print:]]/,"") }1' file 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接