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

依次写出下列输出内容。

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

(0)

相关推荐

  • Javascript lastIndex 正则表达式的一个疑惑

    看下面这段代码: function test(s){ var reg = /./g; console.log(reg.exec(s)); console.log(reg.lastIndex); var reg = /./g; console.log(reg.exec(s)); console.log(reg.lastIndex); } test("abcd"); test("efgh"); 我以为输出的lastIndex的值应该都是1,但是实际上的输出如下: a 1

  • js正则表达式之RegExp对象属性lastIndex,lastMatch,lastParen,lastContext,rightContext属性讲解

    1.lastIndex属性,返回匹配内容的最后一个索引位置,也就是下一个匹配的开始位置,注意字符串索引从0开始 代码: //设置要匹配的内容 var objStr="abfdabcd"; //设置匹配的正则表达式 var re=/abc/; //输出匹配前的字符串 document.write("未匹配前的字符串"+objStr+""); //输出匹配的内容 document.write("匹配的内容"+objStr.matc

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

    依次写出下列输出内容. 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')); //

  • 深入浅析正则表达式中的\B和\b

    对于正则表达式的中\B和\b 有些地方会出现弄不懂的情况 或许你看了下面这篇博客 你就能够对\B和\b认识加深了 根据查看API可以知道 \B和\b都是边界匹配符 先说说\b这个单词边界吧!竟然想了解 首先必须清楚什么叫单词边界!我们可以以\b为分割来探究一下 单词边界 import java.util.regex.Matcher; import java.util.regex.Pattern; public class matcher1 { public static void main(St

  • php中正则表达式中的特殊符号

    字符/  意义:对于字符,通常表示按字面意义,指出接着的字符为特殊字符,不作解释.  例如:/b/匹配字符'b',通过在b 前面加一个反斜杠,也就是/b/,则该字符变成特殊字符,表示  匹配一个单词的分界线.  或者:  对于几个字符,通常说明是特殊的,指出紧接着的字符不是特殊的,而应该按字面解释.  例如:*是一个特殊字符,匹配任意个字符(包括0个字符):例如:/a*/意味匹配0个或多个a.为了匹配字面上的*,在a前面加一个反斜杠:例如:/a*/匹配'a*'. 字符^  意义:表示匹配的字符必

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

    本文实例讲述了正则表达式中的正向预查和负向预查.分享给大家供大家参考.具体分析如下: 这里先来看一个例子,再来解释什么是正向预查. 例子:有一段内容为"coming soon,going gogogo",要求把com和go查找出来.代码如下: 复制代码 代码如下: <html> <head> <script type="text/javascript"> //正向预查 function t1(){  var con = docum

  • 正则表达式中的正向预查和负向预查

    日常工作当中,大多数IDE自带的查找工作都能满足大多数需要. 加上正则匹配简直如虎添翼.匹配个邮箱,电话号什么的不在话下.有时候我们可能会遇到稍微特殊的场景. Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp Windows appeared.

  • 正则表达式预查的详细解释与应用实例

    目录 解释 应用 难点-为什么.?[^#/n]?.*?不行 总结 解释 预查又称环视(Lookaround).属于零宽断言(Zero-Length Assertions)的一种,有 4 个语法: 语法 中文名 英文名 (?=regex) 肯定性前瞻 Positive lookahead (?!regex) 否定性前瞻 Negative lookahead (?<=regex) 肯定性后顾 Positive lookbehind (?<!regex) 否定性后顾 Negative lookbeh

  • JS中正则表达式要注意lastIndex属性

     说明 这篇文章,主要和大家聊聊JavaScript中RegExp对象的属性. 解释 每个RegExp对象都包含5个属性,source.global.ignoreCase.multiline.lastIndex. source:是一个只读的字符串,包含正则表达式的文本. var reg = /JavaScript/; reg.source; //返回 JavaScript global:是一个只读的布尔值,看这个正则表达式是否带有修饰符g. 修饰符g,是全局匹配的意思,检索字符串中所有的匹配.

  • 深入浅析js中的正则表达式

    阅读目录 正则表达式的创建 正则表达式中的特殊字符 \ (反斜杠) ^ $ *,  +,  .(小数点) ? (问号) (x) (?:x) x(?=y), x(?!y), x|y {n}, {n,m}: [xyz], [^xyz] 其他 正则表达式标志 正则表达式使用 很多时候多会被正则表达式搞的晕头转向,最近抽出时间对正则表达式进行了系统的学习,整理如下: 正则表达式的创建 两种方法,一种是直接写,由包含在斜杠之间的模式组成:另一种是调用RegExp对象的构造函数. 两种方法的创建代码如下:

  • 深入浅析正则表达式re模块(部分)

    正则表达式: 官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. ​ 什么是正则表达式: 一套规则 - 匹配字符串的 ​ 谈到正则,就只和字符串相关了.我们要考虑的是在同一个位置上可以出现的字符的范围. ​ 正则表达式能做什么: •1.检测一个输入的字符串是否合法 -- web开发项目 表单验证 ◦用户输入一个内容的时候,我们要提前做检测

  • 正则表达式中问号(?)的正确用法详解

    目录 1.直接跟随在子表达式后面 2.非贪婪匹配 3.非获取匹配 4.断言 参考资料: 正则表达式中“?”的用法大概有以下几种 1.直接跟随在子表达式后面 这种方式是最常用的用法,具体表示匹配前面的一次或者0次,类似于{0,1},如:abc(d)?可匹配abc和abcd 2.非贪婪匹配 关于贪婪和非贪婪,贪婪匹配的意思是,在同一个匹配项中,尽量匹配更多所搜索的字符,非贪婪则相反.正则匹配的默认模式是贪婪模式,当?号跟在如下限制符后面时,使用非贪婪模式(*,+,?,{n},{n,},{n,m})

随机推荐