正则表达式——捕获组的概念探索(JavaScript API)

问题来源

在MDN介绍String.prototype.match()的示例中,举了这么一个例子:

var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);

console.log(found);

// logs [ 'see Chapter 3.4.5.1',
//        'Chapter 3.4.5.1',
//        '.1',
//        index: 22,
//        input: 'For more information, see Chapter 3.4.5.1' ]

// 'see Chapter 3.4.5.1' 是整个匹配。
// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕获。
// '.1' 是被'(\.\d)'捕获的最后一个值。
// 'index' 属性(22) 是整个匹配从零开始的索引。
// 'input' 属性是被解析的原始字符串。

由于这里正则表达式re未使用"g"标志,所以match()仅返回第一个完整匹配及其相关的捕获组。
但是我看的红皮书和MDN文档里均没有关于“捕获组”概念的具体阐述,导致我在看到这里found的输出时产生了疑惑:
为什么found[2]'.1'呢?这里没有加"g"标志,不应该是返回第一个匹配成功的结果吗?照我的理解,这里应该返回'.4'才对;即便加上"g"标志,返回的也不应该是这个结果,而应该是所有匹配项。

独立探索

根据注释中的解释:“’.1’ 是被’(.\d)'捕获的最后一个值。”,我推测捕获组捕获的是匹配的最后一个值,于是做了个小测试。

const pattern = /a(b(.c)*)d/
const res = pattern.exec('ab1cd2c')

按照我的猜测,res[0]res[1]res[2]应该分别为'ab1cd''b1c''2c',但是输出的结果又打了我的脸
res:[ 'ab1cd', 'b1c', '1c', index: 0, input: 'ab1cd2c', groups: undefined ]
res[2]怎么是'1c',也不匹配最后一个值呀?那到底怎么匹配的?

我做了新的猜测:每一个捕获组(即一个小括号,或说一个子模式)内的正则表达式不是作为一个独立的模式去匹配完整的字符串,而是仅保存它在一次完整匹配中所对应的部分。 再以刚刚的代码为例:
模式a(b(.c)*)d非全局匹配字符串'ab1cd2c',匹配结果就是'ab1cd',其中
a(b(.c)*)d对应'ab1cd',即res[0]
子模式b(.c)*对应'b1c',即res[1];
子模式.c对应'1c',也即res[2]

到这里就豁然开朗了,我又做了一些的别的试验,均能证实这样的猜测,这也许就是 “捕获组” 的概念吧,只是限于我没能直接找到这一概念解释,所以花费时间做了这样一番探索。

那么如果是加"g"标志的全局匹配呢?举个栗子🌰:

const pattern = /a(b(.c)*)d/g
const test = 'ab1cd2cab3cd4c'
// 可以看到这里只是将前面的测试字符串加长了一些
const res = pattern.exec(test)
const res2 = pattern.exec(test)
/* res: 
['ab1cd','b1c','1c',index: 0,input: 'ab1cd2cab3cd4c',groups: undefined]
res2:
['ab3cd','b3c','3c',index: 7,input: 'ab1cd2cab3cd4c',groups: undefined]
*/

从这里的结果可以看出,加"g"的情况下,第一次执行的结果和不加"g"没有区别,需要多次执行exec()函数以改变index()的值以进行下一次匹配。这符合JavaScript API中加"g"标志的预期表现。

其他参考

在写这篇文章时看到站内一篇介绍正则表达式中“捕获组”的文章,以供参考: 正则基础之——捕获组(capture group)_josjonah的博客-CSDN博客_正则捕获组
若需熟悉正则表达式基础,可参见ziishaned在GitHub中的正则表达式简洁教程:ziishaned/learn-regex: Learn regex the easy way (github.com)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值