浅析正则表达式中的lastIndex以及预查
依次写出下列输出内容。
varreg1=/a/; varreg2=/a/g; console.log(reg1.test('abcabc'));//true console.log(reg1.test('abcabc'));//true console.log(reg1.test('abcabc'));//true console.log(reg1.test('abcabc'));//true console.log(reg2.test('abcabc'));//true console.log(reg2.test('abcabc'));//true console.log(reg2.test('abcabc'));//false console.log(reg2.test('abcabc'));//true
很简单的一个正则表达式测试,查找字符串abcabc中是否有字符a。但是结果却有一个特殊false存在,Why?
lastIndex(针对于带参数g的正则表达式)
在每个实例化的RegExp对象中,都存在一个lastIndex属性,其初始值为0。
/a/.lastIndex//0 newRegExp('a').lastIndex//0 lastIndex表示匹配成功时候,匹配内容最后一个字符所在原字符串中的位置+1,也就是匹配内容的下一个字符的index(如果匹配内容在字符串的结尾,同样返回原字符串中的位置+1,也就是字符串的length)。如果未带参数g,lastIndex始终为0。 varreg=/ab/g; reg.test('123abc'); console.log(reg.lastIndex)//5 //匹配内容在最后 varreg=/ab/g; reg.test('123ab'); console.log(reg.lastIndex)//5 //不带参数g varreg=/ab/; reg.test('123abc'); console.log(reg.lastIndex)//0
而这个lastIndex也就是用该正则进行其他匹配操作的时候匹配开始的位置。而匹配失败时重置lastIndex为0。
varreg=/ab/g; //初始值为0,从最开始匹配匹配成功,lastIndex为4 console.log(reg.test('12ab34ab'),reg.lastIndex);//true4 //从第4位字符"3"开始匹配匹配内容为第二个ablastIndex为8 console.log(reg.test('12ab34ab'),reg.lastIndex);//true8 //从第8位(字符长度为8,没有第8位)开始匹配匹配不成功重置lastIndex为0 console.log(reg.test('12ab34ab'),reg.lastIndex);//false0 //从头匹配同第一步 console.log(reg.test('12ab34ab'),reg.lastIndex);//true4
看到这里题目也就解答完毕,接下来是扩展。
对于未重新声明的reg容易犯错的地方。
//测试字符串str1和str2是否都含有ab字符 varreg=/ab/g; varstr1='123ab'; varstr2='ab123'; console.log(reg.test(str1));//true console.log(reg.test(str2));//false
很明显这里因为lastIndex的原因导致判断错误。这里可以修改reg不带参数g或则重新声明reg,当然也可以在第一次匹配后手动修改reg.lastIndex=0。
预查
接着说预查,字面意思就是预备匹配查询,也就是查询匹配内容接下来的内容,但是只是预备查询匹配,并不返回。
经常我们需要匹配到字符串中某些字符后面跟某些字符,但是我们不需要匹配结果中包含后面跟的字符,例如:
找出下面字符串中字符后面是2的所有字符。
varstr='a1b2c22d31e4fg6h2'; 'a1b2c22d31e4fg6h2'.match(/[a-z]2/g);//["b2","c2","h2"]
这样,虽然能匹配出字符串带2的,但是数字2我们并不需要,这里只需要字符。而用预查:
'a1b2c22d31e4fg6h2'.match(/[a-z](?=2)/g);//["b","c","h"]
可以看到完全满足条件,但是预查和本文的主题lastIndex又有几毛钱的关系呢?
我们用test来看看,至于为什么用test这里要说明一下,match是匹配所有,直到匹配不成功的时候结束匹配,而匹配不成功时,lastIndex就被重置为0了。
而exec和test是第一次匹配成功或者匹配失败就返回,并不会接着往下匹配。
varreg1=/[a-z](?=2)/g; varreg2=/[a-z]2/g; varstr='a1b2c22d31e4fg6h2'; console.log(reg1.test(str),reg1.lastIndex);//true3 console.log(reg1.test(str),reg1.lastIndex);//true5 console.log(reg1.test(str),reg1.lastIndex);//true16 console.log(reg1.test(str),reg1.lastIndex);//false0 console.log(reg2.test(str),reg2.lastIndex);//true4 console.log(reg2.test(str),reg2.lastIndex);//true6 console.log(reg2.test(str),reg2.lastIndex);//true17 console.log(reg2.test(str),reg2.lastIndex);//false0
看出问题没有?预查的lastIndex不包含预查内容!这里就可以用来简化很多判断了。
例如我们要匹配密码必须有至少一个大写字母,一个小写字母,一个数字,并且长度至少6位而且只能是数字字母组合。
按照不会预查的情况会这样去判断:
/[a-z]/.test(pwd)&&/[A-Z]/.test(pwd)&&/\d/.test(pwd)&&/^[a-zA-Z0-9]{6,}$/.test(pwd);
但是:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z0-9]{6,}$/.test(pwd)
分解出来看:
(?=.*[a-z])是否有小写字母但是是预查匹配失败返回false成功lastIndex不变动,还是为0,同理理解两外预查内容,最后就是6喂以上的字母数字组合匹配,但是前面都是预查,lastIndex始终未0,每次匹配都是从最开始匹配的,所以满足要求。
以上所述是小编给大家介绍的浅析正则表达式中的lastIndex以及预查,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!