JavaScript正则表达式中如何访问匹配组

JavaScript正则表达式中如何访问匹配组

技术背景

在JavaScript里,正则表达式是处理字符串的强大工具,而访问正则表达式中的匹配组是一项常见需求。以往访问多个匹配结果的方式不够直观,因此提出了 String.prototype.matchAll 方法,该方法已被纳入ECMAScript 2020规范。

实现步骤

旧方法

String.prototype.matchAll 方法出现之前,我们可以使用 RegExp.prototype.exec 方法来访问匹配组:

1
2
3
4
5
6
7
8
9
10
11
12
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\\s)format_(.*?)(?:\\s|$)", "g");
var matches = myRegexp.exec(myString);
console.log(matches[1]); // abc

// 处理多个匹配结果
var match;
while (match = myRegexp.exec(myString)) {
console.log(match[0]);
console.log(match.index);
console.log(match[1]);
}

新方法 String.prototype.matchAll

String.prototype.matchAll 方法返回一个迭代器,使用起来更加方便:

1
2
3
4
5
6
7
8
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);

for (const match of matches) {
console.log(match);
console.log(match.index);
}

若需要将结果转换为数组,可以使用扩展运算符或 Array.from 方法:

1
2
3
4
5
6
7
8
9
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}

// 或者
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}

核心代码

自定义 matchAll 方法

1
2
3
4
5
6
7
8
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}

查找所有匹配模式及包含的匹配组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 简洁版本
const searchString = (string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));

// 高性能版本
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};

最佳实践

使用命名组

在ES2018中,可以使用命名组让正则表达式更具可读性:

1
2
3
4
const url = 'https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter';
const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);

使用 String.prototype.replace 处理多个匹配结果

1
2
3
4
5
6
7
8
9
var str = "Our chief weapon is {1}, {0} and {2}!"; 
var params = ['surprise', 'fear', 'ruthless efficiency'];
var patt = /{([^}]+)}/g;

str = str.replace(patt, function(m0, m1, position){
return params[parseInt(m1)];
});

document.write(str);

常见问题

无限循环问题

使用 RegExp.prototype.exec 方法时,如果正则表达式没有全局标志 g,可能会导致无限循环。因此在使用时要确保正则表达式带有全局标志。

浏览器兼容性问题

String.prototype.matchAll 方法并非所有浏览器都支持,在使用时需要查看 浏览器兼容性 信息。若需要在不支持的浏览器中使用,可以使用 官方垫片包


JavaScript正则表达式中如何访问匹配组
https://119291.xyz/posts/javascript-regexp-matched-groups-access/
作者
ww
发布于
2025年5月27日
许可协议