定义
用于检索字符串中的正则表达式的匹配
全局和非全局表达式区别
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
,并不会影响第一次的结果,但是会决定第二次以及以后的结果。
我们可以通过打印regExp
的lastIndex
来验证以上结论是否成立:
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
第一次regExp
的lastIndex
为6, 第二次regExp
的lastIndex
为14, 可以看出每次搜索的起点是在上次匹配结果之后的;
遍历匹配
通过以上的例子,我们知道,当设置全局标志g
,exec
会进行多次匹配,那我们可以对匹配的结果进行遍历,匹配失败将返回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'标记来进行全局的匹配,否则同样会造成死循环
总结
exec
是RegExp
对象的方法,接收参数为字符串;exec
每次执行都返回一个数组:- 正则捕获匹配的字符串;
- 数组包含两个属性:
index
【匹配项在字符串中的位置】和input
【正则表达式的字符串】 - 如果没有找到,则返回值为
null
, 其对应regExp
的lastIndex
也将被重置为0
-
- 不设置全局标志
g
时,exec
方法每次都从头开始检索,并返回第一个匹配项; - 设置全局标志
g
时,exec
方法从上次检索的重点开始检索,也就是lastIndex
值的位置
- 不设置全局标志