【问题标题】:match Vs exec in JavaScript [duplicate]JavaScript中的匹配Vs exec [重复]
【发布时间】:2015-03-01 10:32:42
【问题描述】:

我需要澄清一下 JavaScript 中的 match 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?

【问题讨论】:

    标签: javascript regex


    【解决方案1】:
    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' ]

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

    【讨论】:

      【解决方案2】:

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

      调用匹配相当简单。由于它是一个字符串原型方法,您只需将其链接到一个字符串并提供一个正则表达式作为 match 方法的参数,例如; "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.

      【讨论】:

      • 我认为说“所以如果你有捕获组,exec 是必不可少的”是一种误导,因为.match() 显然确实返回了所有指定捕获组的数组。您在第一句话中暗示了同样多的内容,并且您显然知道每个句子的工作原理。也许您的意思更像是“如果您需要递归应用一个或多个捕获组,使用全局标志和.exec() 是必不可少的”?
      • @Ben Fletcher 谢谢。是的,我指的是在设置全局标志时获取捕获组的情况。然而,现在我们有了String.prototype.matchAll(),它返回一个迭代器对象,该对象在传播时显示所有捕获的组。在上面的答案中提到了编辑。
      猜你喜欢
      • 2013-11-11
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      • 2018-01-20
      • 2018-06-08
      相关资源
      最近更新 更多