在JavaScript中匹配Vs exec

时间:2015-01-03 09:04:29

标签: javascript regex

我需要对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?

2 个答案:

答案 0 :(得分:53)

  1. string.match找到第一个匹配项并返回实际匹配项,找到文本的索引和实际输入,不使用全局标记时。

  2. 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' ]
    
  3. 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);
    }
    

    将返回

    [ '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);
      }
      

答案 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.