深入理解JS正则表达式:捕获与非捕获分组的区别

作者:小括号时间:2026-10-30 10:36:09浏览:140

本文深入解析JavaScript正则表达式中的分组机制,重点区分捕获性分组与非捕获性分组。通过对比(\d+)与(\d)+在贪婪模式下的匹配差异,揭示分组捕获最后一次迭代结果的原理,并介绍(?:pattern)非捕获语法的应用,帮助开发者避免常见正则陷阱。

深入理解JS正则表达式:捕获与非捕获分组的区别

深入理解JS正则表达式---分组

此前曾撰写过一篇关于正则表达式入门的文章,自认为对正则已有一定掌握,但今日又遇到了一个意想不到的问题,或许源于自身不够细致。本文将重点分享JavaScript正则表达式中关于“分组”的知识。若你对JS正则表达式尚不熟悉,可点击此处了解更多基础知识。

分组在正则表达式中的应用十分广泛。从我的理解来看,分组即由一对括号()表示,每一对括号定义一个独立的分组。分组主要可以分为两类:

• 捕获性分组 • 非捕获性分组

捕获性分组及其匹配原理

捕获性分组

在诸如 match 或 exec 等函数中,捕获性分组的结果会以数组的第二项、第三项等形式返回。我们先来看一个具体示例:


var reg = /test(\d+)/;
 var str = 'new test001 test002';
 console.log(str.match(reg));//["test001", "001", index: 4, input: "new test001 test002"]

在代码中,(\d+) 构成一个分组(部分人也称之为子模式),两者含义相同。在上述示例中,test001 是完全匹配的结果。然而,分组的匹配是从整个完全匹配结果(即 test001)中查找与子模式 \d+ 相匹配的字符,此处显然为 001。但今天遇到的情况有所不同:


var reg = /test(\d)+/;
 var str = 'new test001 test002';
 console.log(str.match(reg));//["test001", "1", index: 4, input: "new test001 test002"]

主要区别在于 (\d+) 改为了 (\d)+。整个匹配结果依然是 test001,但第一个分组匹配到的结果却发生了变化。我们将逐步分析两者的区别。

在 (\d+) 的情况下,整个表达式作为一个分组。由于默认情况下匹配模式为贪婪模式,即尽可能多地匹配 \d+ 所能匹配到的结果,因此匹配结果为 001。外层添加的一对括号构成了一个分组,故第一个分组中捕获的结果即为 001。再看第二个示例中的 (\d)+,这同样属于贪婪模式。首先它会匹配字符 0,随后继续匹配 0,最后匹配 1,匹配过程在此结束。表面上看,这与第一个示例的匹配结果似乎没有区别,但这里的分组 (\d) 表示匹配单个数字。按照之前的理解,似乎应该捕获第一个数字 0,但这种理解是错误的。由于整个匹配过程遵循贪婪模式,尽可能多地匹配分组中的 (\d),因此最终捕获的是最后一次匹配到的结果,即 1。如果是非贪婪模式,则会尽可能少地匹配。


 var reg = /test(\d)+?/;
 var str = 'new test001 test002';
 console.log(str.match(reg));//["test001", "0", index: 4, input: "new test001 test002"]

因此,当使用 (\d) 且为非贪婪模式时,匹配结果为 0。尽管后面仍有可匹配的结果,但此处遵循尽可能少匹配的原则。

非捕获性分组的应用

非捕获性分组

非捕获性分组指的是在某些场景下需要使用一对括号,但不希望其成为捕获性分组,即不希望该分组被 match、exec 等函数获取。通常,在括号内部前面加上 ?:,即写成 (?:pattern),即可将其变为非捕获性分组。


var reg = /test(?:\d)+/;
 var str = 'new test001 test002';
 console.log(str.match(reg));//["test001", index: 4, input: "new test001 test002"]

采用这种方式后,match 的结果中将不再包含分组匹配到的内容,即数组中少了第二项的 1。

本文着重说明 (\d+) 和 (\d)+ 的区别,这也是我今天遇到的一个陷阱。若有错误之处,欢迎指正。

以上这篇深入理解JS正则表达式---分组就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

作者最新文章