您可以像这样访问捕获组:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
var match = myRegexp.exec(myString);
console.log(match[1]); // abc
如果有多个匹配项,您可以遍历它们:
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
编辑:2019-09-10
如您所见,迭代多个匹配项的方式不是很直观。这导致了该String.prototype.matchAll
方法的提议。这种新方法预计将在ECMAScript 2020 规范中发布。它为我们提供了一个干净的 API 并解决了多个问题。它已经开始登陆主流浏览器和 JS 引擎,如Chrome 73+ / Node 12+和 Firefox 67+。
该方法返回一个迭代器,用法如下:
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
方法轻松地将结果转换为数组:
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
同时,虽然这个提议得到了更广泛的支持,但你可以使用官方的 shim 包。
此外,该方法的内部工作很简单。使用生成器函数的等效实现如下:
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;
}
}
创建原始正则表达式的副本;这是为了避免lastIndex
在进行多次匹配时由于属性突变而产生的副作用。
此外,我们需要确保正则表达式具有全局标志以避免无限循环。
我也很高兴看到在提案的讨论中甚至引用了这个 StackOverflow 问题。