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

Alb*_*ert 12 sed perl

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

具体来说,从0x00到 的所有字符0x1F,除了0x09(TAB), 0x0A(new line), 0x0D(CR)

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

perl -p -e 's/\x0/ /g' $FILE_IN > $FILE_OUT 
Run Code Online (Sandbox Code Playgroud)

现在我在 Linux 上工作,所以我希望能够使用sed命令。

我的问题:

  • 此命令是否适合替换这些字符?我试过了,它似乎有效,但我想确保:

    perl -p -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUT  
    
    Run Code Online (Sandbox Code Playgroud)
  • 我认为perl -p作为sed. 那么,为什么上一个命令有效(至少,它不会失败),而下一个命令无效?

    sed -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUT   
    
    Run Code Online (Sandbox Code Playgroud)

    它告诉我:

    sed:-e 表达式 #1,字符 34:无效的排序规则字符

Sté*_*las 11

这是一个典型的工作tr

LC_ALL=C tr '\0-\10\13\14\16-\37' '[ *]' < in > out
Run Code Online (Sandbox Code Playgroud)

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

您还可以相信您的语言环境关于可打印字符的想法:

tr -c '[:print:]\t\r\n' '[ *]'
Run Code Online (Sandbox Code Playgroud)

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

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

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

sed 's/[^[:print:]\r\t]/ /g' < in > out
Run Code Online (Sandbox Code Playgroud)

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

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