正则捕获的 懒惰性

🌙
手机阅读
本文目录结构

正则捕获的懒惰性

  • exec 每执行一次,只能捕获到一个符合规则的内容;
  • 默认状态下,无论我们执行多少次,都只能捕获到第一个匹配的数据,其余的捕获不到
  • 默认情况下,只能捕获到第一个数据,这种现象叫正则的懒惰性;

reg.lastIndex

reg.lastIndex 表示当前正则下一次匹配的起始索引位置;

let str = "axihe2020an06bang30";
let reg = /\d+/;
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//true
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//true

第一次匹配捕获完成,lastIndex 没有改变,所以下一次 exec 依然输从字符串最开始查找,找的永远都是第一个匹配到的数据。

正则的懒惰性的原因

正则的懒惰性的原因:默认情况下,lastIndex 的值不会被修改,每一次都是从字符串开始位置查找,所以找到的永远都是第一个内容。

下面我们尝试手动修改 lastIndex, 发现改不了。

let str = "axihe2020an06bang30";
let reg = /\d+/;
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//true
reg.lastIndex = 11
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//true

修饰符g可以解决正则懒惰性

let str = "axihe2020an06bang30";
let reg = /\d+/g;
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//["2020", index: 5, input: "axihe2020an06bang30", groups: undefined]
console.log(reg.lastIndex);//9
console.log(reg.exec(str));//["06", index: 11, input: "axihe2020an06bang30", groups: undefined]
console.log(reg.lastIndex);//13
console.log(reg.exec(str));//["30", index: 17, input: "axihe2020an06bang30", groups: undefined]
console.log(reg.lastIndex);//19
console.log(reg.exec(str));//null

我们总结一下

  • 修饰符g可以解决正则懒惰性的核心是:g可以更改lastIndex
  • 当全局捕获都已完成以后,再次捕获的结果是 null;
  • lastIndex 再捕获结果为 null 的时候回归到初始值 0,如果再进行捕获就开始循环啦;

test 方法可以打破正则懒惰性

let str = "axihe2020an06bang30";
let reg = /\d+/g;
//验证:只有正则和字符串匹配我们再捕获
if (reg.test(str)) {
    console.log(reg.lastIndex);//9
    console.log(reg.exec(str));//["06", index: 11, input: "axihe2020an06bang30", groups: undefined]
    console.log(reg.test(str));//true
    console.log(reg.lastIndex);//19
}

我们总结:

  • test 可以把 lastIndex 修改
  • test 改为当前匹配后的结果(下次匹配不再是预期的位置了)

编写 execAll 方法

编写 execAll 方法,执行一次可以把所有匹配的结果捕获到,前提正则一定要设置全局修饰符;

如何验证一个正则是否设置了修饰符g

let reg = /\d+/g;
console.dir(reg)

输出结果

dotAll: false
flags: "g"
global: true
ignoreCase: false
lastIndex: 0
multiline: (...)
source: (...)
sticky: (...)
unicode: (...)
__proto__: Object

可以通过 reg.global 是否为 true 判断正则的修饰符;

如何写execAll


let str = "axihe2020an06bang30";
(() => {
    // execAll 参数str : 要匹配的字符
    // execAll 中的this: RegExp的实例(当前操作的正则)
    // 注意` function (str = "")`不能用箭头函数
    RegExp.prototype.execAll = function (str = "") {
        let ary = [],
            res = this.exec(str);//每次捕获到的内容

        if (!this.global) {
            return res;
        }
        // 只要捕获的不为null
        while (res) {
            ary.push(res[0])
            res = this.exec(str);
        }
        return ary.length ? ary : null;
    }
})()
let reg = /\d+/g;
console.dir(reg);//可以在`__proto__`上看到execAll方法
console.log(reg.execAll(str));//["2020", "06", "30"]
console.log(reg.execAll('axihe.com'));//null

match是打破正则懒惰性的最优解

字符串的match方法,可以在执行一次的情况下,捕获到所有匹配的数据;

前提:正则也需要设置修饰符g;

let str = "axihe2020an06bang30";
let reg1 = /\d+/;
let reg2 = /\d+/g;
console.log(str.match(reg1));//["2020", index: 5, input: "axihe2020an06bang30", groups: undefined]
console.log(str.match(reg2));// ["2020", "06", "30"]

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了