我需要用文件中的空格替换一些不可打印的字符。
具体来说,从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 要求的集合的一部分))。
如果有的话,它不会转换不形成有效字符的字节。