![如何使用 sed 进行搜索和替换,但在第一个匹配组之后使用数字(匹配组的正确转义)](https://linux22.com/image/210376/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20sed%20%E8%BF%9B%E8%A1%8C%E6%90%9C%E7%B4%A2%E5%92%8C%E6%9B%BF%E6%8D%A2%EF%BC%8C%E4%BD%86%E5%9C%A8%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%B9%E9%85%8D%E7%BB%84%E4%B9%8B%E5%90%8E%E4%BD%BF%E7%94%A8%E6%95%B0%E5%AD%97%EF%BC%88%E5%8C%B9%E9%85%8D%E7%BB%84%E7%9A%84%E6%AD%A3%E7%A1%AE%E8%BD%AC%E4%B9%89%EF%BC%89.png)
前言
也许你想转换这个:
aaaa
到:
1aaa1
所以让我们提出这样的建议:
echo aaaa | sed --regexp-extended 's/(.*)a/1\11/'
→
1aaa1
问题
是1\11
100% 有效且明确的sed
模式吗?我是否遵守了sed
此类替换的所有良好实践?
我的意思是1\11
或许可能是这两者:
- 替换为 char
1
,然后是 1° 匹配组,然后是另一个 char1
(→ 当前行为) - 替换为字符
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}
。我想这样的规定或类似的规定通常是为了避免混淆。