为什么 sed 不替换 NULL 字符 \x0?

Why sed doesn't replace NULL-characters \x0?

如果我想替换几行,例如在文件或 STDIN 中,并且我不知道文件或 STDIN 中出现的行数,我可以将整个流程合并为一个行,例如 tr,像这样:

$ printf "%s\n" aaa bbb ccc ddd | tr '\n' '[=10=]' | sed -e 's#bbb\x0ccc\x0ddd#string2\x0string3\x0string4#g' | tr '[=10=]' '\n'

aaa
bbb
ccc
ddd

我想在这种情况下得出这样的结论:

aaa
string2
string3
string4

请注意,这是一个测试示例,在实际情况下,我不知道要进行替换的行数。我只知道需要替换的行和需要替换的行。

据我所知,sed可以替换NULL字符,例如:

printf "%s\n" aaa bbb ccc ddd | tr '\n' '[=12=]' | sed -e 's#\x0#\n#g'
aaa
bbb
ccc
ddd

为什么第一种情况没有发生?

你可以尝试用正则表达式替换它 - (.*)而不是\x0,但是输入数据不同,它会导致替换错误,如下例:

$printf "%s\n" aaa bbb ccc ddd bbb ddd | tr '\n' '[=13=]' | sed -e 's#bbb\(.*\)ccc\(.*\)ddd#string2string3string4#g' | tr '[=13=]' '\n'

aaa
string2
string3
ddd
bbb
string4

你能告诉我如何正确替换多行吗?感谢您的帮助!

问题似乎是 \x 转义消耗的不仅仅是 1 零。 考虑在 \x0c 中,0c 都是有效的十六进制数字。

十六进制转义的工作方式因语言而异。 例如,在 C 语言中,它们超级贪婪(将尽可能消耗所有有效的十六进制数字)。 非宽字符串的更明智的 \x 转义将恰好消耗两位数(以便填充一个 8 位字节)。 Sed 的版本似乎是这样工作的。

根据实验,将 \x0 替换为 \x00 有效:

printf "%s\n" aaa bbb ccc ddd | tr '\n' '[=10=]' | sed -e 's#bbb\x00ccc\x00ddd#string2\x00string3\x00string4#g' | tr '[=10=]' '\n'