GNU awk:在替换文本中访问捕获组

49

这似乎应该很简单,但是awk的gensub/gsub/sub行为对我来说一直不太清楚,现在我无法让它按照文档所说的去做(以及与其他类似工具的经验表明应该可以工作的方式)。具体而言,我想从替换字符串中访问正则表达式中的“捕获组”。以下是我认为awk语法应该如下:

awk '{ gsub(/a(b*)c/, "Here are bees: \1"); print; }'
那应该把 "abbbc" 转换成 "Here are bees: bbb"。但是在 Ubuntu 9.04 上,至少对我而言它没有转换成功。相反, "\1" 被渲染为 ^A;也就是说,它变成了字符代码为1的字符。这当然不是我想要的结果。我该怎么做呢?
谢谢。
2个回答

48

使用GNU awk:

echo abbc | awk '{ print gensub(/a(b*)c/, "Here are bees: \\1", "g", $1);}'

请查看此处的手册,了解gsub和gensub之间的区别

gensub()提供了一个附加功能,sub()或gsub()中不可用:在替换文本中指定正则表达式的组件。这是通过在正则表达式中使用括号标记组件,然后在替换文本中指定“\N”,其中N是从1到9的数字来完成的。


9
不仅gsub和gensub在返回值方面表现不同,而且整个\1到\9功能只能与gensub一起使用。 - Pointy
尝试使用echo xxxabbcxxx命令 - awk的“解决方案”会出现问题。 - Aleksandr Levchuk
@Alesandr,随意提出新的建议。 - user180100
1
@AleksandrLevchuk 您的示例完全按预期工作。我认为这个解决方案没有任何问题。它进行替换,然后返回完整的变量。 - Sparhawk
看到有人因为不理解语法或没有阅读手册而声称某种编程语言“有问题”,这让我感到很好笑! - Medievalist
了解如何获取完整匹配的文本是很有用的:与sub()函数一样,您必须输入两个反斜杠才能将一个反斜杠放入字符串中。在替换文本中,序列'\0'表示整个匹配的文本,字符'&'也表示整个匹配的文本。 - undefined

31

根据gawk手册

gensub提供了一项额外的功能,sub或gsub中不可用: 可以在替换文本中指定正则表达式的组成部分。 这是通过在正则表达式中使用括号标记组件, 然后在替换文本中指定“\N”来实现的, 其中N是从1到9的数字。

您必须使用gensub,必须指定"g",并且必须获取gensub的结果,因为它不会进行原地修改。

awk '{ r = gensub(/a(b*)c/, "Here are bees: \\1", "g"); print r; }'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接