我需要对JavaScript中的匹配Vs exec进行一些澄清; here有人说是
“带有全局正则表达式的exec意味着在循环中使用”但首先如你在我的例子中看到的那样情况并非如此;在我的示例exec中使用全局正则表达式返回数组中的所有匹配项!其次他们说对于String.match它返回所有匹配而不需要循环!但是再一次,我的例子中没有发生这种情况,只是返回输入字符串?我误解了/做错了什么吗?
var myString = "[22].[44].[33].";
var myRegexp = /.*\[(\d*)*\].*\[(\d*)*\].*\[(\d*)*\].*/g;
var execResult = myRegexp.exec(myString);
console.log(execResult.length);
console.log(execResult[1]);// returns 22 and execResult has all of my matches from index 1 to the length of array
var matchResult = myString.match(myRegexp);
console.log(matchResult.length);
console.log(matchResult);// returns just myString which is "[22].[44].[33]."! Why is that?
答案 0 :(得分:53)
string.match
找到第一个匹配项并返回实际匹配项,找到文本的索引和实际输入,不使用全局标记时。
string.match
只返回所有匹配项,使用全局标记时。
var myString = "[22].[44].[33].";
console.log(myString.match(/\d+/));
# [ '22', index: 1, input: '[22].[44].[33].' ]
console.log(myString.match(/\d+/g));
# [ '22', '44', '33' ]
string.match
与regex.exec
之间的主要区别在于,regex
对象将更新当前与regex.exec
电话的匹配。对于例如,
var myString = "[22].[44].[33].", myRegexp = /\d+/g, result;
while (result = myRegexp.exec(myString)) {
console.log(result, myRegexp.lastIndex);
}
将返回
[ '22', index: 1, input: '[22].[44].[33].' ] 3
[ '44', index: 6, input: '[22].[44].[33].' ] 8
[ '33', index: 11, input: '[22].[44].[33].' ] 13
如您所见,只要找到匹配项,就会更新lastIndex
属性。因此,在使用exec
时要记住两件事,否则会遇到无限循环。
如果您没有使用g
选项,那么您将始终获得第一场比赛(如果有),否则null
。因此,以下将会遇到无限循环。
var myString = "[22].[44].[33].", myRegexp = /\d+/, result;
while (result = myRegexp.exec(myString)) {
console.log(result, myRegexp.lastIndex);
}
不要忘记在后续调用中使用相同的正则表达式对象。因为,每次都会更新正则表达式对象,如果传递新对象,程序将再次进入无限循环。
var myString = "[22].[44].[33].", result;
while (result = /\d+/g.exec(myString)) {
console.log(result);
}
答案 1 :(得分:3)
String.prototype.match()
和RegExp.prototype.exec()
在查找多个匹配项并将其返回到数组中时类似。然而,exec方法返回一组更详细的信息。例如,与匹配不同,它也可以找到多次出现的捕获组。因此,如果你有捕获组,exec是必不可少的。使用exec时要记住的一件事是,如果来自文字正则表达式,则不应该调用。首先将正则表达式赋给变量并使用它来调用exec方法。另一件事是,虽然匹配会一次性在一个项目数组中出现多次出现,但是对于exec,你必须为每个要捕获的事件进行迭代。
调用匹配非常简单。因为它是一个字符串原型方法,你只需将它链接到一个字符串,并提供一个regexp作为匹配方法的参数,如; “test”.match(/ es /)正则表达式的文字表示可以毫无问题地使用。
调用exec更复杂。正如我之前提到的,最好将正则表达式分配给之前的东西。好的,让我们看一个例子
var text = '["job name 1","nat 1"],["job name 2","nat 2"],["job name 3","nat 3"]',
reg = /([^"]+)","([^"]+)/g,
tm = [],
te = [];
tm = text.match(reg); // tm has result of match
while(te[te.length]=reg.exec(text)); // te has result of exec + an extra null item at the end
te.length--; // te normalized.
document.write("<pre>" + JSON.stringify(tm,null,2) + "</pre>\n");
document.write("<pre>" + JSON.stringify(te,null,2) + "</pre>\n");
如您所见,exec的结果还包括捕获组。我选择填充te
数组的方式有点不正统,但我讨厌在while循环的条件部分使用临时数组。这让我看起来更整洁。唯一的事情是,停止while循环的最后一个null被插入到te
数组的末尾。因此,以下te.length--
指令。
编辑:现在,现代浏览器中还提供了String.prototype.matchAll()功能,这些功能主要解除了使用exec的负担。 You may look another answer of mine to see that in action.