用`sed` vs`tr`替换空字节

时间:2017-03-04 05:43:50

标签: bash sed

Bash新手;用这个成语生成一个字符串的重复:

echo $(head -c $numrepeats /dev/zero | tr '\0' 'S')

我决定用多个字符替换每个空字节(例如' MyString'而不仅仅是' S'),所以我尝试了以下sed

echo $(head -c $numrepeats /dev/zero | sed 's/\0/MyString/g' )

但我得到一个空输出。我意识到我必须做

echo $(head -c $numrepeats /dev/zero | sed 's/\x0/MyString/g' )

echo $(head -c $numrepeats /dev/zero | sed 's/\x00/MyString/g' )
相反,但我不明白为什么。 trsed匹配的字符之间有什么区别?是因为sed与正则表达式匹配吗?

修改 有趣的发现\0 replacement命令的's/regexp/replacement'部分sed实际上与&的行为相同。仍然没有解释为什么\0中的regexp与nullbyte不匹配(正如在tr和大多数其他正则表达式实现中那样)

3 个答案:

答案 0 :(得分:3)

从tr(1)的手册页:

  

SET被指定为字符串...解释的序列是:
        \ NNN字符,八进制值NNN(1到3个八进制数字)

对于sed(1),手册页不是那么清楚,所以一些尝试可以显示:

echo -n hi |sed 's/h/t/g' |hexdump -c    (0000000   t   i)

易。然后:

echo -n hi |sed 's/h//g' |hexdump -c      (0000000   i)

空模式删除匹配项。再简单。然后:

echo -n hi |sed 's/h/\0/g' |hexdump -c    (0000000   h   i)

这个\ 0似乎什么都不做。所以试试

echo -n hi |sed 's/h/\00/g' |hexdump -c   (0000000   h   0   i)

哦!是否可以将\ 0作为匹配部分的参考?这也可以解释前面的例子。 sed man page谈到\ 1到\ 9,而不是\ 0(但是\ 0无论如何都有意义,即使在模式规范中也是如此。)

所以,简而言之:对于sed,\ 0有一个特殊含义,不是一个NUL字符。但它理解八进制:

echo -n hi |sed 's/h/\o0/g' |hexdump -c    (0000000  \0   i)

和十六进制:

echo -n hi |sed 's/h/\x0/g' |hexdump -c    (0000000  \0   i)

正如评论中指出的那样,tr和sed是不同的工具,设计不同。是的,sed使用regexp而tr没有,但这不是关于\ 0的一般解释不同的解释。在unix凌乱的世界中,通常有一些惯例。在unix的凌乱世界中, more 经常是这些约定的例外。

答案 1 :(得分:1)

问题中的后两个命令确实有效:

$ sed --version
sed (GNU sed) 4.4
Packaged by Cygwin (4.4-1)

$ echo -e "Hello\0World" | hexdump.exe -c
0000000   H   e   l   l   o  \0   W   o   r   l   d  \n                
000000c

$ echo -e "Hello\0World" | sed 's/\x0/MyString/g'
HelloMyStringWorld

$ echo -e "Hello\0World" | sed 's/\x00/MyString/g'
HelloMyStringWorld

八进制序列必须以\o为前缀(谢谢, Benjamin W。,对于此提示):

$ echo -e "Hello\0World" | sed 's/\o0/MyString/g'
HelloMyStringWorld

因此,OP中必定存在另一个问题。

答案 2 :(得分:1)

特殊问题:本身没有trsed 。相反,这些程序的版本跨时间和操作系统平台。一般来说,UNIX的历史是一个快速变化的花期;更具体地说,tr在1973年发布用于版本4 Unix,而sed在1979年首次出现在版本7 Unix中。从一开始,这些是由不同的作者在不同的{{1}上编写的。对于不同的shell,具有不同的目的(注意:Bash在1989年写得很多,而不是"所有者和#34;这些实用程序中的任何一个)。并且,就这些程序如何独立演化,维护(由不同的作者),如何/修复了哪些错误等而言,事情变得更加多样化和复杂。尽管最近已经做出很多努力来标准化核心实用程序,但是ossed以完全相同的方式处理字符是无法理解历史,麻烦的缺乏标准以及奇怪的有益的多个UNIX本身。