RegExp之exec使用详解

2,357 阅读3分钟

定义

用于检索字符串中的正则表达式的匹配

全局和非全局表达式区别

exec方法使用全局和非全局表达式返回结果是不同, 我们可以通过两个例子来讲解一下:

非全局表达式

let str="web2.0 .net2.0";
let pattern=/(\w+)(\d)\.(\d)/;//没有全局标志g
console.log(pattern.exec(str));

现在我们来逐个分析一下结果:

  • 第一项:web2.0, 与整个模式匹配的结果,也就是与*/(\w+)(\d)\.(\d)/*匹配的结果;

  • 第二项:web,与第一个匹配组匹配的结果,也就是与*(\w+)*匹配的结果;

  • 第三项:2,与第二个匹配组匹配的结果,也就是与*(\d)*匹配的结果;

  • 第四项:0,与第三个匹配组匹配的结果,也就是与*(\d)*(第二个(\d))匹配的结果;

  • 属性一:index:0,匹配项在字符串中的位置,也就是数组第一项的匹配字符串的位置。

  • 属性二:input:"web2.0 .net2.0",也就是输入参数str。

这个时候,如果我们再执行一次exec方法:

let str="web2.0 .net2.0";
let pattern=/(\w+)(\d)\.(\d)/;//没有全局标志g
console.log(pattern.exec(str));
console.log(pattern.exec(str));

两次结果如下(都是相同的)

原因: 当不设置全局标志 g, exec方法每次都从头开始检索,并返回第一个匹配项;

第一次匹配第一次匹配

全局表达式

设置全局标志 g, exec方法从上次检索的终点开始检索

let str="web2.0 .net2.0";
let pattern=/(\w+)(\d)\.(\d)/g;//有全局标志g
console.log(pattern.exec(str));
console.log(pattern.exec(str));

两次结果如下:

第一次匹配第二次匹配

结论:可以看出两次结果是不同的,第二次结果是在第一次结果的基础上往后继续查找,而不是从头开始。因为是否设置全局标志 g,并不会影响第一次的结果,但是会决定第二次以及以后的结果。

我们可以通过打印regExplastIndex来验证以上结论是否成立:

let str="web2.0 .net2.0";
let pattern=/(\w+)(\d)\.(\d)/g;//有全局标志g
let match1= pattern.exec(str);
console.log(pattern.lastIndex);//6
let match2= pattern.exec(str);
console.log(pattern.lastIndex);//14

第一次regExplastIndex为6, 第二次regExplastIndex为14, 可以看出每次搜索的起点是在上次匹配结果之后的;

遍历匹配

通过以上的例子,我们知道,当设置全局标志gexec会进行多次匹配,那我们可以对匹配的结果进行遍历,匹配失败将返回null

let str="web2.0 .net2.0";
let pattern=/(\w+)(\d)\.(\d)/g;//有全局标志g
let arr = pattern.exec(str);

while(arr !== null) {
    console.log(`匹配${arr[0]}成功,该结果的起始位置在${pattern.lastIndex}`);
    // 匹配web2.0成功,该结果的起始位置在6
    // 匹配net2.0成功,该结果的起始位置在14
    arr = pattern.exec(str);
}

注意:

  • 不要把正则表达式字面量(或者RegExp构造器)放在 while 条件表达式里。由于每次迭代时 lastIndex 的属性都被重置,如果匹配,将会造成一个死循环

  • 并且要确保使用了'g'标记来进行全局的匹配,否则同样会造成死循环

总结

  1. execRegExp对象的方法,接收参数为字符串;
  2. exec每次执行都返回一个数组:
    1. 正则捕获匹配的字符串;
    2. 数组包含两个属性:index【匹配项在字符串中的位置】和 input【正则表达式的字符串】
    3. 如果没有找到,则返回值为null, 其对应regExplastIndex也将被重置为0
    • 不设置全局标志g时,exec方法每次都从头开始检索,并返回第一个匹配项;
    • 设置全局标志g时,exec方法从上次检索的重点开始检索,也就是lastIndex值的位置

参考

RegExp MDN