JavaScript正则表达式和子匹配

时间:2009-05-09 20:34:09

标签: javascript regex

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

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年后你现在可以做到这一点(.matchAll已添加到规范中)

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

2 个答案:

答案 0 :(得分:94)

如果设置了全局修改器,则使用String的{​​{1}}函数将不会返回捕获的组。

在这种情况下,您可能希望使用match()对象并调用其RegExp函数。 exec()的{​​{1}}几乎与String的{​​{1}}函数相同......除非是这样的情况。如果设置了全局修改器,则普通match()函数将不会返回捕获的组,而RegExp的{​​{1}}函数将会返回。 (注意here,以及其他地方。)

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

所以,例如,你可以这样做:

RegExp

需要注意的另一件事是exec()exec()在提供的字符串上执行正则表达式并返回第一个结果。每个顺序调用都将根据字符串中的当前位置逐步更新结果集null

这是一个例子:     //记住示例和模式中有4个匹配项。 lastIndex从0开始

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()个对象on the MDN的信息(具体来说,这里是the exec() function的文档)。

答案 1 :(得分:0)

我很惊讶地发现我是第一个回答我十年前寻找的答案的人(答案尚不存在)。我还希望实际的规范作者会在我之前回答它;)。

.matchAll 已被添加到一些浏览器中。

在现代javascript中,我们现在可以通过执行以下操作来完成此操作。

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

.matchAll spec

.matchAll docs

我现在维护一个同构的javascript库,该库可以帮助处理许多此类字符串。您可以在这里进行检查:string-saw。使用命名捕获组时,它有助于简化.matchAll的使用。

一个例子是

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

这会输出更加用户友好的匹配项数组,如果您想花哨的话,可以抛出命名的捕获组并获取对象数组。