Bash 新手;使用这个习语来生成一个字符串的重复:
echo $(head -c $numrepeats /dev/zero | tr '\0' 'S')
Run Code Online (Sandbox Code Playgroud)
我决定用多个字符替换每个空字节(例如,“MyString”而不是“S”),所以我用 sed 尝试了以下操作
echo $(head -c $numrepeats /dev/zero | sed 's/\0/MyString/g' )
Run Code Online (Sandbox Code Playgroud)
但我只是得到一个空的输出。我意识到我必须做
echo $(head -c $numrepeats /dev/zero | sed 's/\x0/MyString/g' )
Run Code Online (Sandbox Code Playgroud)
或者
echo $(head -c $numrepeats /dev/zero | sed 's/\x00/MyString/g' )
Run Code Online (Sandbox Code Playgroud)
相反,但我不明白为什么。tr和sed匹配的字符有什么区别?是因为sed匹配正则表达式吗?
编辑
有趣的发现,\0在命令的replacement部分's/regexp/replacement' sed实际上与&. 仍然没有解释为什么\0inregexp与空字节不匹配(正如它在tr和大多数其他正则表达式实现中所做的那样)
从 tr(1) 的手册页:
SET 被指定为字符串......解释的序列是:
\NNN 字符与八进制值 NNN(1 到 3 个八进制数字)
对于 sed(1),手册页不是很清楚,因此尝试几次可以显示一些内容:
echo -n hi |sed 's/h/t/g' |hexdump -c (0000000 t i)
Run Code Online (Sandbox Code Playgroud)
简单。然后:
echo -n hi |sed 's/h//g' |hexdump -c (0000000 i)
Run Code Online (Sandbox Code Playgroud)
空模式删除匹配。又轻松。然后:
echo -n hi |sed 's/h/\0/g' |hexdump -c (0000000 h i)
Run Code Online (Sandbox Code Playgroud)
这个 \0 似乎什么都不做。所以试试
echo -n hi |sed 's/h/\00/g' |hexdump -c (0000000 h 0 i)
Run Code Online (Sandbox Code Playgroud)
哦!是否可以将 \0 作为对匹配部分的引用?这也可以解释前面的例子。sed 手册页谈论的是 \1 到 \9,而不是 \0(但 \0 无论如何都有含义,即使在模式规范中也是如此)。
因此,简而言之:对于 sed,\0 具有特殊含义,它不是NUL 字符。但它理解八进制:
echo -n hi |sed 's/h/\o0/g' |hexdump -c (0000000 \0 i)
Run Code Online (Sandbox Code Playgroud)
和十六进制:
echo -n hi |sed 's/h/\x0/g' |hexdump -c (0000000 \0 i)
Run Code Online (Sandbox Code Playgroud)
正如评论中指出的, tr 和 sed 是不同的工具,设计不同。是的,sed 使用正则表达式而 tr 不使用,但这不是关于 \0 的一般解释,解释方式不同。在混乱的 unix 世界中,通常有一些约定。在混乱的 unix 世界中,更多情况下,这些约定有例外。