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

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

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

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:无效的排序字符

答案1

这是一个典型的工作tr

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

就您而言,它不起作用,sed因为您所在的区域设置中这些范围没有意义。如果您想使用字节值而不是字符,并且顺序基于这些字节的数值,那么最好的选择是使用 C 语言环境。你的代码本来可以LC_ALL=C与 GNU一起使用sed,但是使用sed(更不用说perl)在这里有点矫枉过正(而且这些方法\xXX在实现上是不可移植的,sed而这种tr方法是 POSIX 的)。

您还可以相信您所在地区的想法可打印字符有:

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

但对于 GNU tr(通常在基于 Linux 的系统上发现),它仅适用于字符为单字节的语言环境(通常不是 UTF-8)。

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

在 UTF-8 语言环境中,您可以使用 GNU sed,它不会出现 GNUtr所存在的问题:

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

(请注意,那些\r,\t不是标准的,如果在环境中, GNUsed不会识别它们(将它们视为反斜杠,r 和 t 是 POSIX 要求的集合的一部分))。POSIXLY_CORRECT

但它不会转换不形成有效字符的字节(如果有的话)。

答案2

我试图通过 libnotify 发送通知,其内容可能包含无法打印的字符。现有的解决方案对我来说不太有效(使用tr有效的字符白名单,但会删除任何多字节字符)。

这是有效的,同时通过了

相关内容