【发布时间】:2022-01-21 02:51:08
【问题描述】:
如果我想替换几行,例如在一个文件或 STDIN 中,我不知道文件或 STDIN 中出现的行数,我可以将整个流程变成一行,例如tr,像这样:
$ printf "%s\n" aaa bbb ccc ddd | tr '\n' '\0' | sed -e 's#bbb\x0ccc\x0ddd#string2\x0string3\x0string4#g' | tr '\0' '\n'
aaa
bbb
ccc
ddd
我想在这种情况下得到这个结论:
aaa
string2
string3
string4
请注意,这是一个测试示例,在实际情况下,我不知道要进行替换的行数。我只知道需要替换的行和需要替换的行。
据我所知,sed 可以替换 NULL 字符,例如:
printf "%s\n" aaa bbb ccc ddd | tr '\n' '\0' | sed -e 's#\x0#\n#g'
aaa
bbb
ccc
ddd
为什么第一种情况没有发生?
您可以尝试用正则表达式替换它-(.*)而不是\x0,但是输入数据不同,会导致替换错误,如下例所示:
$printf "%s\n" aaa bbb ccc ddd bbb ddd | tr '\n' '\0' | sed -e 's#bbb\(.*\)ccc\(.*\)ddd#string2\1string3\2string4#g' | tr '\0' '\n'
aaa
string2
string3
ddd
bbb
string4
您能告诉我如何正确替换多行吗?感谢您的帮助!
【问题讨论】:
-
sed是用 C 编写的。NUL 不能出现在 C 字符串中。因此,期望sed的常见实现能够容忍模式缓冲区内的 NUL,除非sed的特定实现被设计和记录为不遗余力地这样做本身就是一个延伸。 -
(尽管正如 PSkocik 所说,
\x0根本不是 NUL 的完全逃脱,所以这里有一个明显的脱节) -
将所有
\ns 转换为\0s,就像您对tr '\n' '\0'所做的那样,将有效的POSIX 文本文件变成无效的文件(通过删除所需的最终\n)等等YMMV 以及任何后续文本处理工具(例如sed)将其作为输入。不过,您永远不需要这样做,因此,如果您认为您需要针对某些特定应用程序,请发布一个新问题,我们会为您提供帮助。