为什么Javascript子匹配在设置g
修饰符时停止工作?
var text = 'test test test test';
var result = text.match(/t(e)(s)t/);
// Result: ["test", "e", "s"]
Run Code Online (Sandbox Code Playgroud)
上述工作正常,result[1]
是"e"
和result[2]
是"s"
.
var result = text.match(/t(e)(s)t/g);
// Result: ["test", "test", "test", "test"]
Run Code Online (Sandbox Code Playgroud)
以上忽略了我的捕获组.以下是唯一有效的解决方案吗?
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"]
*/
Run Code Online (Sandbox Code Playgroud)
hbw*_*hbw 95
如果设置了全局修改器,使用String
的match()
函数将不会返回捕获的组,如您所知.
在这种情况下,您可能希望使用RegExp
对象并调用其exec()
函数.String
的match()
几乎是相同RegExp
的exec()
,除了在这样的情况下功能.......如果全局修改设置,正常的match()
功能将不返回拍摄组,而RegExp
的exec()
功能.(在这里注明,等等.)
要记住的另一个问题是,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...
}
Run Code Online (Sandbox Code Playgroud)
另外要注意的是,RegExp.prototype.exec()
和RegExp.prototype.test()
执行上提供的字符串的正则表达式,返回的第一个结果.每个顺序调用将RegExp.prototype.lastIndex
根据字符串中的当前位置逐步执行结果集更新.
这是一个例子://记住示例和模式中有4个匹配项.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);
}
Run Code Online (Sandbox Code Playgroud)
您可以在MDN上找到有关如何使用RegExp
对象的信息(具体来说,这是该函数的文档).exec()
我很惊讶地发现我是第一个用 10 年前我一直在寻找的答案来回答这个问题的人(答案还不存在)。我也希望实际的规范编写者能在我之前回答这个问题;)。
.matchAll已添加到一些浏览器中。
在现代 javascript 中,我们现在只需执行以下操作即可完成此任务。
let result = [...text.matchAll(/t(e)(s)t/g)];
Run Code Online (Sandbox Code Playgroud)
我现在维护一个同构 javascript 库,它可以帮助进行很多此类字符串解析。您可以在这里查看:string-saw。在使用命名捕获组时,它有助于使 .matchAll 更易于使用。
一个例子是
saw(text).matchAll(/t(e)(s)t/g)
Run Code Online (Sandbox Code Playgroud)
它会输出更加用户友好的匹配数组,如果您想要更奇特,您可以放入命名捕获组并获取对象数组。
归档时间: |
|
查看次数: |
29301 次 |
最近记录: |