JavaScript 正则表达式和子匹配

为什么 Javascript 子匹配在设置 g修饰符时停止工作?

var text = 'test test test test';


var result = text.match(/t(e)(s)t/);
// Result: ["test", "e", "s"]

以上工作正常,result[1]"e"result[2]"s"

var result = text.match(/t(e)(s)t/g);
// Result: ["test", "test", "test", "test"]

上面忽略了我的捕获组。以下是唯一有效的解决方案吗?

var result = text.match(/test/g);
for (var i in result) {
console.log(result[i].match(/t(e)(s)t/));
}
/* Result:
["test", "e", "s"]
["test", "e", "s"]
["test", "e", "s"]
["test", "e", "s"]
*/

编辑:

我又回来高兴地告诉你,10年后你现在可以做到这一点(。Match All 已被添加到规范中)

let result = [...text.matchAll(/t(e)(s)t/g)];
34806 次浏览

如果设置了全局修饰符,那么使用 Stringmatch()函数将不会返回捕获的组,正如您所发现的。

在这种情况下,您需要使用一个 RegExp对象并调用它的 exec()函数。Stringmatch()几乎与 RegExpexec()功能完全相同,除了这种情况。如果设置了全局修饰符,普通的 match()函数将不返回捕获的组,而 RegExpexec()函数将返回捕获的组。(注意 给你,以及其他地方)

需要记住的另一个问题是,exec()不会在一个大数组中返回匹配项ーー它会一直返回匹配项,直到用完为止,在这种情况下,它会返回 null

例如,你可以这样做:

var pattern = /t(e)(s)t/g;  // Alternatively, "new RegExp('t(e)(s)t', 'g');"
var match;


while (match = pattern.exec(text)) {
// Do something with the match (["test", "e", "s"]) here...
}

另一件需要注意的事情是,RegExp.prototype.exec()RegExp.prototype.test()对提供的字符串执行正则表达式并返回第一个结果。每个顺序调用将逐步通过根据字符串中的当前位置更新 RegExp.prototype.lastIndex的结果集。

这里有一个例子: //记住示例中有4个匹配项,而 pattern. lastIndex 从0开始

pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9
pattern.exec(text); // pattern.lastIndex = 14
pattern.exec(text); // pattern.lastIndex = 19


// if we were to call pattern.exec(text) again it would return null and reset the pattern.lastIndex to 0
while (var match = pattern.exec(text)) {
// never gets run because we already traversed the string
console.log(match);
}


pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9


// however we can reset the lastIndex and it will give us the ability to traverse the string from the start again or any specific position in the string
pattern.lastIndex = 0;


while (var match = pattern.exec(text)) {
// outputs all matches
console.log(match);
}

您可以找到有关如何使用 RegExp对象 在 MDN 上的信息(具体来说,这里是 exec()函数的文档)。

我很惊讶地发现,我是第一个用10年前我一直在寻找的答案来回答这个问题的人(这个答案当时还不存在)。我还希望真正的规格说明书编写者会在我之前回答这个问题;)。

. match All 已经被添加到一些浏览器中。

在现代的 javascript 中,我们现在可以通过执行以下操作来实现这一点。

let result = [...text.matchAll(/t(e)(s)t/g)];

。匹配所有规格

。匹配所有文件

我现在维护一个同构的 javascript 库,它可以帮助解析大量这种类型的字符串。你可以在这里查看: 绳锯。它有助于制造。在使用命名捕获组时,match All 更容易使用。

举个例子

saw(text).matchAll(/t(e)(s)t/g)

它输出一个更加用户友好的匹配数组,如果您想获得更好的匹配,可以添加命名的捕获组并获得一个对象数组。