代码如下:
var text = 'mom and dad and baby'; var pattern = /(mom( (and (dad))( and baby)?)?)?/g; var pattern = /( and dad( and baby)?)?/g; var matches = pattern.exec(text);
当pattern为第二行所示代码时,matches有匹配值,但是当pattern为第三行代码时,matches中无匹配值,而将第三行代码最后的问号去掉后又有匹配值了。为什么第二行中可以在最后加上问号,而第三行中不行呢。谢谢!
为了说明方便,把你的两个正则重新命名如下
var text = 'mom and dad and baby'; var pattern1 = /(mom( (and (dad))( and baby)?)?)?/g; var pattern2 = /( and dad( and baby)?)?/g; var pattern3 = /( and dad( and baby)?)/g; var matches1 = pattern1.exec(text); var matches2 = pattern2.exec(text); var matches3 = pattern3.exec(text);
首先说明的是pattern2并不是无匹配值,匹配结果matches2是数组["", undefined, undefined]。
正则的匹配过程是从左到右的,并且是以最大可能的方式进行匹配的。
对于pattern1,会在text的最开始获得匹配并且整个字符串"mom and dad and baby"都得到匹配,于是其匹配结果matches1将是数组["mom and dad and baby", "mom and dad and baby", " and dad and baby", "and dad", "dad", " and baby"];
对于pattern2而言,在字符串text的伊始就获得匹配,但是匹配的是text最开始的空字符串(""),因为pattern最外层存在一个问号,也就是可以匹配到空串。因此matches2将是数组["", undefined, undefined];
对于pattern3,由于其最外层没有问号,因此在字符串text伊始并无法获得匹配,于是正则从左到右匹配,搜索到"and dad"时获得匹配,并且由于正则是以最大可能的方式进行匹配的,所以子匹配( and baby)?也将一并匹配。也就是pattern匹配到text中的"and dad and baby";于是matches3将是数组[" and dad and baby", " and dad and baby", " and baby"]
额外补充:正则的exec匹配结果是一个数组array;array[0]是整个正则的匹配字符串,array[n] (n>0)是正则表达式各子表达式所匹配到的字符串。
谢谢你的回答,我还有一个问题,是不是说括号里的子匹配是在整个正则匹配到的字符串的基础上的呢。
以pattern2为例,因为整个正则匹配到'',所以后面的子匹配就相当于and dad( and baby)?.exec(''),请问是这样吗,如果不是的话,后面几个值为什么是undefined呢。谢谢!
@美儿宝: 不是的,正则的匹配是一个整体性过程,不是一个递归迭代过程,子表达式的结果还要依赖于整个表达式(顺序、位置等因素)。也就是说,直接将整个表达式的匹配结果去匹配子表达式所得的匹配结果并不一定就是子表达式的匹配结果。
@孤独傲雪: 这样的话为什么matches2的array[1]和array[2]是undefined呢,而matches3的是有值的。因为pattern2和pattern3的子表达式都分别是 and dad( and baby)?(array[1])和 and baby(array[2]),那么应该可以匹配到一样的字符串吧。
麻烦你了。