替换perl和sed中不可打印的字符


11

我需要用文件中的空格替换一些不可打印的字符。

具体来说,所有字符0x00最多到0x1F,但0x09(TAB),0x0A(新行),0x0D(CR)除外

到目前为止,我只需要替换0x00字符即可。因为我以前的操作系统是AIX(没有GNU命令),所以我不能使用sed(虽然可以,但是有一些限制)。因此,我找到了使用的下perl一条命令,该命令按预期工作:

perl -p -e 's/\x0/ /g' $FILE_IN > $FILE_OUT 

现在我正在Linux上工作,因此我希望能够使用sed命令。

我的问题:

  • 此命令是否适合替换那些字符?我尝试过,而且似乎可行,但是我想确保:

    perl -p -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUT  
  • 我以为perl -p工作sed。那么,为什么上一个命令起作用(至少不会失败),而下一个命令却不起作用?

    sed -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUT   

    它告诉我:

    sed:-e表达式#1,字符34:无效的归类字符


perl -pstdin完成所需的操作后打印最终产品,在这种情况下,它只是替换产品。sed的regex可能与perl
sdkks

Answers:


11

这是典型的工作tr

LC_ALL=C tr '\0-\10\13\14\16-\37' '[ *]' < in > out

在您的情况下,它不起作用,sed因为您所处的语言环境对这些范围没有意义。如果要使用字节值而不是字符,并且顺序基于这些字节的数值,则最好的选择是使用C语言环境。您的代码可以LC_ALL=C与GNU 一起使用sed,但是使用sed(更不用说perl)在这里有点过大(并且当这种方法是POSIX 时,它们\xXX不能跨sed实现移植tr)。

您还可以信任您的语言环境对可打印字符的看法:

tr -c '[:print:]\t\r\n' '[ *]'

但是,对于GNU tr(通常在基于Linux的系统中可以找到),它仅在字符为单字节的语言环境中起作用(因此,通常不是UTF-8)。

在C语言环境中,这还将排除DEL(0x7f)和以上所有字节值(不是ASCII)。

在UTF-8语言环境中,您可以使用GNU sed,它不存在GNU存在的问题tr

sed 's/[^[:print:]\r\t]/ /g' < in > out

(注意,这些\r\t都是不规范,以及GNU sed如果不承认他们POSIXLY_CORRECT是在环境(将它们视为反斜杠,R和T属于该组的一部分,POSIX要求))。

即使有,它也不会转换不构成有效字符的字节。


我了解tr命令的作用。我了解(或多或少)什么LC_ALL = C是,但不是全部一起。尽管如此,tr -d删除那些字符,但我想用空格代替。抱歉,标题错误。我刚刚意识到,@ don_crissti进行了修改。
艾伯特

@Albert,对不起。查看修改内容和我添加的链接。
斯特凡Chazelas

我不确定编码。该文件来自使用EBCDIC编码的HOST环境,并使用传输到Linux XCOM。例如,非ASCII字符之类É的代码(使用od -xa)编码为0xC9,所以我想应该是ISO-8859-1
艾伯特

@Albert,可能。您可以locale -a用来查看系统上是否存在以iso8859-1作为字符集的语言环境,并可以LC_CTYPE=<that-locale> tr ...[:print:]...用来转换该语言环境中的非可打印内容。或者,您可以使用iconv将这些文件转换为区域设置的字符集。
斯特凡Chazelas

我认为不需要,因为我的语言环境的字符集设置为LC_ALL=en_US.iso88591。因此,您的命令(tr -c '[:print:]\t\r\n' '[ *]')完美运行,而无需修改语言环境或转换文件。非常感谢。
艾伯特

0

我试图通过libnotify发送通知,内容可能包含无法打印的字符。现有的解决方案对我而言并不十分有效(使用Works使用字符白名单tr,但会删除所有多字节字符)。

这是通过while测试的有效方法:

message=$(iconv --from-code=UTF-8 -c <<< "$message")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.