在 JavaScript 中匹配 Vs exec

match Vs exec in JavaScript

我需要对 JavaScript 中的 match 与 exec 进行一些说明; here 有人说

"exec with a global regular expression is meant to be used in a loop" 但首先正如您在我的示例中看到的那样,情况并非如此;在我的示例中,带有全局正则表达式的 exec 返回数组中的所有匹配项!其次,他们说 String.match 它 returns 所有匹配都不需要循环!但是在我的示例中又没有发生这种情况,它只是返回输入字符串?我 misunderstood/done 有什么问题吗?

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?
  1. string.match 找到第一个匹配项并 return 将其与实际匹配项、找到文本的索引和实际输入进行比较,当不使用全局标志时。

  2. string.match只是return所有匹配,当使用全局标志时。

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.matchregex.exec 之间的主要区别在于,regex 对象将通过 regex.exec 调用更新当前匹配。 例如,

var myString = "[22].[44].[33].", myRegexp = /\d+/g, result;

while (result = myRegexp.exec(myString)) {
    console.log(result, myRegexp.lastIndex);
}

将return

[ '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 时要记住两件事,否则 你将 运行 陷入无限循环。

  1. 如果你不使用g选项,那么你总是会得到第一个匹配项,如果有的话,否则null。所以,下面会运行进入死循环

    var myString = "[22].[44].[33].", myRegexp = /\d+/, result;
    
    while (result = myRegexp.exec(myString)) {
        console.log(result, myRegexp.lastIndex);
    }
    
  2. 不要忘记在后续调用中使用相同的正则表达式对象。因为,正则表达式对象每次都会更新,如果你传递新对象,程序将再次运行进入无限循环。

    var myString = "[22].[44].[33].", result;
    
    while (result = /\d+/g.exec(myString)) {
        console.log(result);
    }
    

String.prototype.match()RegExp.prototype.exec() 在查找多个匹配项并将它们返回到数组中方面相似。然而exec方法returns一个数组的信息更详细。例如,与 match 不同,它也可以找到多次出现的捕获组。所以如果你有捕获组,exec 是必不可少的。在使用 exec 时要记住一件事,你不应该从文字正则表达式中调用 if 。首先将您的正则表达式分配给一个变量,然后使用它来调用您的 exec 方法。另一件事是,虽然 match 会一次性在项目数组中出现多次,但使用 exec 时,您必须迭代以捕获每次出现的事件。

调用匹配非常简单。由于它是一个字符串原型方法,您只需将它链接到一个字符串并提供一个正则表达式作为匹配方法的参数,例如; "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() functionality available in modern browsers which mostly lifts the burden of using exec over our shoulders. You may look another answer of mine to see that in action.