正则的捕获
实现正则捕获的方法
- 正则RegExp.prototype上的方法
- exec
- test
- 字符串String.prototype上支持正则表达式处理的方法
- replace
- match
- split
- ....
//实现捕获的要求是,正则必须匹配这个目标字符串,如果不匹配,捕获的结果是null
let str = "wozai2019,xuexizhengze,20191015"
let reg = /\d+/;
/*
* 基于exec实现正则的捕获
* 1. 捕获到的结果是null或者一个数组
* 数组第一项: 本次捕获到的内容
* (如果有分组(用小括号实现))其余项: 对应小分组本次单独捕获的内容
* 每一项详解: index----当前捕获内容在字符串中的起始索引
* input-----原始字符串
* 2. 每执行一次exec只能捕获到一个符合正则规则,但是默认情况下,执行多次,获取到的结果永远都是第一个匹配到的, 其余的捕获不到(正则捕获的懒惰性)
*/
console.log(reg.exec(str)); // => ["2019", index: 5, input: "wozai2019,xuexizhengze,20191015", groups: undefined]
/*
* lastIndex: 当前正则下一次匹配的起始索引位置
* reg.lastIndex 默认是0,从0开始匹配(所以,正则捕获的懒惰性,是因为如果不指定的话,正则的lastIndex总是0)(懒惰性不是只有exec方法,这是正则的特性)
*/
// lastIndex手动修改是没有用的,全局匹配可以达到这个目的(lastIndex会自动修改)
let str = "wozai2019,xuexizhengze,20191015"
let reg = /\d+/g;
reg.exec(str);
console.log(reg.lastIndex) // 9 (从第一个2019后边开始)
reg.exec(str); // 如果将字符串捕获彻底之后,再次捕获的结果是null,但是lastIndex又变成初始值0
// 因此,解决正则的懒惰性 ------ 加全局g
/ *
* let reg = /^\d+$/;
* console.log(reg.text(str)); // => false
* consolle.log(reg.exec(str)); // => null
* /
如果我们要使用捕获exec,基于以上已知知识,很自然的会写出这种代码:
let reg = /\d+/g;
if(reg.test(str)){ // 我们知道,只有在正则匹配字符串的时候,才能捕获到不为null的结果,这样写好像没问题
console.log(reg.exec(str))
console.log(reg.lastIndex)
}
运行
所以,全局匹配g会改变lastIndex,不管使用的是什么(test,exec)方法,因为懒惰性是正则的特性
。
但是,如你所见,exec每次只能捕获一个,肯定有这种需求,需要一次全部捕获,接下来,我们实现一个execAll方法
~function(){
function execAll(str){ //str:要匹配的字符串,默认为空字符串
// 前提,目标正则必须要加全局“g”,如果不加,则在while处会死循环
// 因此,第一步要先判断
if(!this.global) return this.exec(str);
let ary= [],
res = this.exec(str);
while (res) {
// 把每次捕获到的内容(长度为1的数组)的第一项push到结果数组中
ary.push(res[0])
// => 只要捕获的内容不是null,则继续捕获下去
res = this.exec(str);
}
return ary.length === 0 ? null : ary; //这里为了和字符串的match方法一致
}
RegExp.prototype.execAll = execAll;
}()
var str = "234sdfsdf56756df56756rtfdgdfgvbxcv4566";
var reg = /\d+/g;
console.log(reg.execAll(str)); // ["234", "56756", "56756", "4566"]
以上正则的全局捕获方法,在字符串中有原生的实现——match
console.log("234sdfsdf56756df56756rtfdgdfgvbxcv4566".match(/\d+/g))
// ["234", "56756", "56756", "4566"]
再强调一次,我们实现的execAll是正则的方法;match是字符串的方法
网友评论