浅析正则表达式中的lastIndex以及预查

所属分类: 网络编程 / 正则表达式 阅读数: 1513
收藏 0 赞 0 分享

依次写出下列输出内容。

var reg1 = /a/;
var reg2 = /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
new RegExp('a').lastIndex // 0
lastIndex表示匹配成功时候,匹配内容最后一个字符所在原字符串中的位置 + 1,也就是匹配内容的下一个字符的index(如果匹配内容在字符串的结尾,同样返回原字符串中的位置 + 1,也就是字符串的length)。如果未带参数g,lastIndex始终为0。
var reg = /ab/g;
reg.test('123abc');
console.log(reg.lastIndex) // 5
// 匹配内容在最后
var reg = /ab/g;
reg.test('123ab');
console.log(reg.lastIndex) // 5
// 不带参数g
var reg = /ab/;
reg.test('123abc');
console.log(reg.lastIndex) // 0

而这个lastIndex也就是用该正则进行其他匹配操作的时候匹配开始的位置。而匹配失败时重置lastIndex为0。

var reg = /ab/g;
// 初始值为0,从最开始匹配 匹配成功, lastIndex为4
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4
// 从第4位字符"3"开始匹配 匹配内容为第二个ab lastIndex 为 8
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 8
// 从第8位 (字符长度为8,没有第8位) 开始匹配 匹配不成功 重置lastIndex 为 0
console.log(reg.test('12ab34ab'), reg.lastIndex); // false 0
// 从头匹配 同第一步
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4

看到这里题目也就解答完毕,接下来是扩展。

对于未重新声明的reg容易犯错的地方。

// 测试字符串str1 和 str2 是否都含有ab字符
var reg = /ab/g;
var str1 = '123ab';
var str2 = 'ab123';
console.log(reg.test(str1)); // true
console.log(reg.test(str2)); // false

很明显这里因为lastIndex的原因导致判断错误。这里可以修改reg不带参数g或则重新声明reg,当然也可以在第一次匹配后手动修改reg.lastIndex = 0。

预查

接着说预查,字面意思就是预备匹配查询,也就是查询匹配内容接下来的内容,但是只是预备查询匹配,并不返回。

经常我们需要匹配到字符串中某些字符后面跟某些字符,但是我们不需要匹配结果中包含后面跟的字符,例如:

找出下面字符串中字符后面是2的所有字符。

var str = '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是第一次匹配成功或者匹配失败就返回,并不会接着往下匹配。

var reg1 = /[a-z](?=2)/g;
var reg2 = /[a-z]2/g;
var str = 'a1b2c22d31e4fg6h2';
console.log(reg1.test(str), reg1.lastIndex); // true 3
console.log(reg1.test(str), reg1.lastIndex); // true 5
console.log(reg1.test(str), reg1.lastIndex); // true 16
console.log(reg1.test(str), reg1.lastIndex); // false 0
console.log(reg2.test(str), reg2.lastIndex); // true 4
console.log(reg2.test(str), reg2.lastIndex); // true 6
console.log(reg2.test(str), reg2.lastIndex); // true 17
console.log(reg2.test(str), reg2.lastIndex); // false 0

看出问题没有?预查的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以及预查,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

正则表达式详细介绍(上)

这篇文章主要介绍了正则表达式,正则表达式是由英文词语regular expression翻译过来的,就是符合某种规则的表达式。本文将会详细的介绍正则表达式,需要的朋友可以参考下
收藏 0 赞 0 分享

正则表达式详细介绍(下)

这篇文章继续介绍了更多关于正则表达式知识点,帮助大家更好的认识正则表达式,从而更好的掌握它,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

比较常用证件正则表达式验证大全

最近做项目,有项目需求需要对各种常用的证件进行验证。而港澳通行证,台湾通行证,护照这些证件,在网上没有搜到正则验证的方法,后来经过一番折腾,结合validator这个验证插件写了一些代码,在此分享给大家,需要的朋友可以参考下
收藏 0 赞 0 分享

正则表达式实现将MM/DD/YYYY格式的日期转换为YYYY-MM-DD格式

这篇文章主要介绍了正则表达式实现将MM/DD/YYYY格式的日期转换为YYYY-MM-DD格式的方法,是一个比较简单实用的正则替换应用,对于怎能则表达式的学习具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

js使用正则子表达式匹配首字母与尾字母相同单词的方法

这篇文章主要介绍了js使用正则子表达式匹配首字母与尾字母相同单词的方法,可实现将多行文本框中首位字母相同的单词进行匹配的功能,具有一定参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

正则表达式中的正向预查和负向预查实例分析

这篇文章主要介绍了正则表达式中的正向预查和负向预查,实例分析了正向预查和负向预查的概念与具体用法,具有一定参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

js正则表达式中的单行模式与多行模式实例分析

这篇文章主要介绍了js正则表达式中的单行模式与多行模式,实例分析了js正则表达式中实现单行模式与多行模式的技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

js正则查找match()与替换replace()用法实例

这篇文章主要介绍了js正则查找match()与替换replace()用法,实例分析了js中正则的查找match()与替换replace()的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

js正则表达式test()和exec()用法实例

这篇文章主要介绍了js正则表达式test()和exec()用法,实例分析了test()函数和exec()函数在进行正则匹配时的使用技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

php正则替换变量指定字符的方法

这篇文章主要介绍了php正则替换变量指定字符的方法,涉及php使用正则表达式进行字符串替换的技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多