如何使用 sed 进行搜索和替换,但在第一个匹配组之后使用数字(匹配组的正确转义)

如何使用 sed 进行搜索和替换,但在第一个匹配组之后使用数字(匹配组的正确转义)

前言

也许你想转换这个:

aaaa

到:

1aaa1

所以让我们提出这样的建议:

echo aaaa | sed --regexp-extended 's/(.*)a/1\11/'
1aaa1

问题

1\11100% 有效且明确的sed模式吗?我是否遵守了sed此类替换的所有良好实践?

我的意思是1\11 或许可能是这两者:

  1. 替换为 char 1,然后是 1° 匹配组,然后是另一个 char 1(→ 当前行为)
  2. 替换为字符1,然后11° 匹配组(→ 导致异常)

目前看来我的 sed 版本有第一种解释。无论如何,我不知道这是否有记录,或者是否可以在sed.

感谢您的任何澄清。同时我不会在此基础上建造一座城堡。

目前我正在使用 GNU sed 4.7。

答案1

正如用户 @QuartzCristal 所说,在 GNU 的sed手册页中有这样一条注释:

s/正则表达式/替换/

尝试将正则表达式与模式空间进行匹配。如果成功,则替换与替换匹配的部分。替换可能包含特殊字符 & 来引用模式空间中匹配的部分,以及特殊转义符 \1 到 \9 来引用正则表达式中相应的匹配子表达式。

1来自通用编程语言(如 Perl),从到没有这种限制9(因为例如您可以编写1{$19}1),我没有意识到sed.所以,我知道目前语法是 100% 正确的,不能以其他方式解释。

这个答案对 GNU sed 有效。不确定它是 POSIX 定义。

答案2

有一个POSIX 中的描述内容如下:

反向引用表达式 '\n' 应与 '\n' 之前的“(”和“)”之间的子表达式匹配的字符串相同(可能为空)。字符“n”应为从 1 到 9 的数字,指定第 n 个子表达式(从模式开头的第 n 个“(”开始并以相应的成对“)”结束的子表达式)。

这将避免任何\10\11.

这是 BRE 的语法,但我们不需要担心 POSIX 中的 ERE,因为它们不允许反向引用。

GNU sed 手册也有同样的规定。我不相信有任何 sed 允许比\1...\9反向引用更多的功能。

此外,替换的右侧s///可能包含捕获括号的引用。那些是Posix 中没有明确划分

字符“\n”(其中 n 是数字)应替换为与相应反向引用表达式匹配的文本。

但它似乎使用与反向引用相同的规则。

GNU sed 确实明确指出:

反向引用用反斜杠和单个数字(例如“\1”)指定。

Perl 是一种允许更多反向引用的语言。但在该语言中,会编写超过一位数字的反向引用${23}。我想这样的规定或类似的规定通常是为了避免混淆。

相关内容