首页 > 解决方案 > 使用 sed 删除不可打印的字符不起作用

问题描述

我正在使用 AIX unix 并尝试从文件中删除不可打印的字符, in Arizona w/ fiancÃÂÃÂÃÂ当我使用 UTF-8 编码在 Notepad++ 中查看时,数据看起来像在文件中。当我尝试在 unix 中查看文件时,我得到 ^▒▒^▒▒^▒▒^▒▒^▒▒^▒▒

我想用空格替换所有这些特殊字符,我的输出应该看起来像in Arizona w/ fianc

我试过sed 's/[^[:print:]]/ /g' file 了,但它没有删除那些字符。当我运行时,我的语言环境在下面列出locale -a

C
POSIX
en_US.8859-15
en_US.ISO8859-1
en_US

我什至尝试过sed -e 's/[^ -~]/ /g',它没有删除字符。

我看到其他堆栈流答案使用UTF-8带有 GNU sed 的语言环境,这有效,但我没有那个语言环境。

我也在使用ksh.

标签: unixsedkshnon-printing-characters

解决方案


最简单的 -strings

最简单的方法是使用以下strings命令:

$ cat  /tmp/asdf
in Arizona w/ fiancÃÂÃÂÃÂ
$ strings  /tmp/asdf
in Arizona w/ fianc

这种方法的问题:

  • 它没有使用 sed
  • 每当找到任何不可打印的字符时,它都会添加一个行尾(在您的示例中应该没问题,因为它们都在最后分组,但否则会失败)

最丑 -sedlsed后处理

现在,如果您必须使用sed,那么这里有一个替代方案:

$ sed -n l /tmp/asdf | sed -E 's/\\[[:digit:]]{3}//g; s/\$$//'
in Arizona w/ fianc

在这里,您l用于“转储”不可打印的字符,将它们转换为八进制表示形式,例如\303,然后删除任何看起来像这样创建的八进制值的内容,然后删除$添加l在行尾的内容。

它有点难看,并且可能与您的文件交互不良,如果它有任何以反斜杠开头后跟三位数字的内容,所以我会保留该strings选项。

更好 -sed具有高 Unicode 字符的范围

下面的也是一个hack,但看起来比其他的要好。它使用sed范围,以“¡”开头。我选择那个符号是因为它是 iso-8859-1 编码中的第二个*字符,它也恰好是 ASCII 之后的 Unicode 部分。所以,我猜你没有遇到实际控制代码的问题,而是使用非 ASCII 字符(任何表示超过 127 个十进制的字符)。

对于范围中的第二个项目,只需选择一些非拉丁字符(日语、中文、希伯来语、阿拉伯语等),希望它在 Unicode 中足够高以包含您的任何“非打印”字符。

不幸的是,sed没有[[:ascii:]]范围。它都不接受开放式范围,因此您需要此技巧。

$ sed 's/[¡-ﺏ]/ /g' /tmp/asdf
in Arizona w/ fianc

(*)注意:我选择了范围内的第二个字符,因为第一个字符是一个不间断的空格,所以很难理解它不仅仅是一个普通的空格。


推荐阅读