正则表达式分组为何只捕获最后一个匹配呢?

将正则表达式“(\d)+”应用于文本“123456789”,分组$1的数值是9,分组只捕获最后一个匹配值么? [图片]
关注者
11
被浏览
9,931
登录后你可以
不限量看优质回答 私信答主深度交流 精彩内容一键收藏

这个问题我十多年前学正则的时候就研究过了。是的,当分组带上量词,正则单次匹配完后,分组仍保留的匹配值只有它最后一次匹配到的字符串,在 JavaScript 中可以通过 $1 来获取到:

> "123".replace(/(\d)+/, "$1")
> RegExp.$1
'3'

但这并不意味着该分组就真的只匹配了 3,在匹配过程中它是匹配了 3 次的,但那是正则引擎内部的过程,我们拿不到另外两个值。

在 10 多年前还流行一点的 Perl 语言中,它也是大部分现代正则语法的创造者,是可以通过一种高级的正则语法 (?{}) 来内嵌任意代码,从而实现查看正则引擎的匹配过程:

> perl -le '"123456789" =~ /(\d(?{print "分组匹配了:", $1}))+/'
分组匹配了:
分组匹配了:1
分组匹配了:2
分组匹配了:3
分组匹配了:4
分组匹配了:5
分组匹配了:6
分组匹配了:7
分组匹配了:8

这个就是说,当正则引擎每匹配到一次 (\d,就输出一次 $1,注意由于第一次输出时右边的小括号还没闭合,所以输出了空,最后一次输出了 8 而不是 9 也是这个原因,稍微修改一下就对了:

> perl -le '"123456789" =~ /(?:(\d)(?{print "分组匹配了:", $1}))+/'
分组匹配了:1
分组匹配了:2
分组匹配了:3
分组匹配了:4