【发布时间】:2014-04-16 18:59:16
【问题描述】:
我正在尝试使用 sed,最近我发现了一些有趣的行为。但是,我找不到任何描述它的文档。
假设我们有一个名为“sedtest”的文件:
$cat sedtest
hello 0 world
example
4 sed
Phone number: 123-456-789
接下来,我将通过 sed 运行它:
$cat sedtest | sed '/\([[:digit:]]\+\)/s,,(\1),'
hello (0) world
example
(4) sed
Phone number: (123)-456-789
这是相当容易理解的 sed 脚本:
- 首先,它通过正则表达式
\([[:digit:]]\+\)匹配字符串,这意味着“匹配包含1个或多个数字的字符串”。请注意,我在这里还使用s-command-style\(和\)括号来标记子字符串(是否允许?)。 - 如果匹配,它会继续使用
s命令s,,(\1),(带有空的正则表达式字段),这意味着“将匹配的子字符串替换为(\1)”。
最初我认为它应该会因错误而失败,因为\1 和类似的反向引用应该只适用于来自s 命令匹配器字段的子字符串,在这种情况下它是空的。
但结果就像是s,\([[:digit:]]\+\),(\1), 脚本(\regexp\ 匹配器移入s 命令匹配器字段)!
所以,问题是:从s//replace/ 命令反向引用由\regexp\ 规则匹配的文本子串是否正常(即,它是期望的行为),就像它们被s/regexp/replace/ 命令匹配一样?
附言
我的 sed 版本是:GNU sed 4.2.1
问题背后的动机是你可以这样做:
sed '/^Number: \([[:digit:]]\+\)$/{s,,#NUMBER: (\1),;p;d};q 1',即
-
/^Number: \([[:digit:]]\+\)$/- 匹配Number: 12345的每一个字符串,如果匹配:-
s,,#NUMBER: (\1),- 将其替换为#NUMBER: (12345) -
p- 打印出来 -
d- 清除模式空间,开始新循环(获取新行并从头开始解析脚本表达式)
-
-
q 1- 使用代码 1 退出。此命令仅在步骤 1 中未发生匹配时执行(因为d命令存在) - 它检查“不匹配”的情况,在我的情况下意味着“不允许的字符串”并且必须导致错误。
这里的主要技巧是在替换发生后执行p 和d 命令,这在使用“普通”s/match/replace/ 命令时是不可能的。
【问题讨论】:
标签: sed