为什么在设置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)];
答案 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)];
我现在维护一个同构的javascript库,该库可以帮助处理许多此类字符串。您可以在这里进行检查:string-saw。使用命名捕获组时,它有助于简化.matchAll的使用。
一个例子是
saw(text).matchAll(/t(e)(s)t/g)
这会输出更加用户友好的匹配项数组,如果您想花哨的话,可以抛出命名的捕获组并获取对象数组。