![替换 perl 和 sed 中的不可打印字符](https://linux22.com/image/64500/%E6%9B%BF%E6%8D%A2%20perl%20%E5%92%8C%20sed%20%E4%B8%AD%E7%9A%84%E4%B8%8D%E5%8F%AF%E6%89%93%E5%8D%B0%E5%AD%97%E7%AC%A6.png)
我需要用文件中的空格替换一些不可打印的字符。
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
有效的字符白名单,但会删除任何多字节字符)。
这是有效的,同时通过了