正则表达式两种创建方式区别以及捕获特性

209 阅读2分钟

正则两种创建方式的区别

构造函数因为传递的是字符串,\需要写两个才代表斜杠

let reg = /^/d+$/g;
reg = new RegExp('\\d+','g');

正则表达是中的部分内容是变量存储的值

1.两个斜杠中间包起来的都是元字符(如果正则中要包含某个变量的值,则不能使用字面量方式创建)

let type = "zhufeng";
reg = /^@"+type+"@$/; 
console.log(reg.test("@zhufeng@")); //=>false
console.log(reg.test('@"""typeeeee"@')); //=>true

2.这种情况只能使用构造函数方式(因为它传递的规则是字符串,只有这样才能进行字符串拼接)

reg = new RegExp("^@"+type+"@$");
console.log(reg.test("@zhufeng@"));//=>true

正则的捕获

  • 正则RegExp.prototype上的方法
    • exec
    • test
  • 字符串String.prototype上支持正则表达式处理的方法
    • replace
    • match
    • splite
    • .......
let str = "zhufeng2019yangfan2020qihang2021";
let reg = /\d+/;

基于exec实现正则的捕获

1.捕获到的结果是null或者一个数组
  第一项:本次捕获到的内容
  其余项:对应小分组本次单独捕获的内容
  index:当前捕获内容在字符串中的起始索引
  input:原始字符串
2.每执行一次exec,只能捕获到一个符合正则规则的,但是默认情况下,我们执行一百遍,获取的结果永远都是第一个匹配到的,其余的捕获不到
   “正则捕获的懒惰性”:默认只捕获第一个
   
console.log(reg.exec(str)); //=>["2019", index: 7, input: "zhufeng2019yangfan2020qihang2021"]
console.log(reg.exec(str)); //=>["2019"...]

实现正则捕获的前提是:当前正则要和字符串匹配,如果不匹配捕获的结果是null

let reg = /^\d+$/;
console.log(reg.test(str)); //=>false
console.log(reg.exec(str)); //=>null

懒惰性的解决办法

let str = "zhufeng2019yangfan2020qihang2021";

/*
 * reg.lastIndex:当前正则下一次匹配的起始索引位置 
 *   懒惰性捕获的原因:默认情况下lastIndex的值不会被修改,每一次都是从字符串开始位置查找,所以找到的永远只是第一个
 *   解决办法:全局修饰符g
 */
let reg = /\d+/;
console.log(reg.lastIndex); //=>0 下面匹配捕获是从STR索引零的位置开始找
console.log(reg.exec(str));
console.log(reg.lastIndex); //=>0 第一次匹配捕获完成,lastIndex没有改变,所以下一次exec依然是从字符串最开始找,找到的永远是第一个匹配到的

let reg = /\d+/g;
console.log(reg.exec(str)); //=>["2019"...]
console.log(reg.lastIndex); //=>11 设置全局匹配修饰符g后,第一次匹配完,lastIndex会自己修改
console.log(reg.exec(str)); //=>["2020"...]
console.log(reg.lastIndex); //=>22
console.log(reg.exec(str)); //=>["2021"...]
console.log(reg.lastIndex); //=>32
console.log(reg.exec(str)); //=>null 当全部捕获后,再次捕获的结果是null,但是lastIndex又回归了初始值零,再次捕获又从第一个开始了...
console.log(reg.lastIndex); //=>0
console.log(reg.exec(str)); //=>["2019"...]

let reg = /\d+/g;
//验证一下:只有正则和字符串匹配我们在捕获
//错误的做法:
if (reg.test(str)) {
    console.log(reg.lastIndex); //11
    //基于TEST匹配验证后,LASTINDEX已经被修改为第一次匹配后的结果,所以下一次捕获不再从头开始了
    console.log(reg.exec(str)); //=>["2020"...]
}

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

第一种:
~function (){
	function execAll(str = ""){
    	//str:要匹配的字符串
        //this:RegExp的实例(当前操作的正则)
        //进来后的第一件事,是验证当前正则是否设置了G,不设置则不能在进行循环捕获了,否则会导致死循环
        if(!this.blobal) return this.exec(str);
        //ARY存储最后所有捕获的信息  RES存储每一次捕获的内容(数组)
        let ary = [],
        	res = this.exec(str);
        while(res){
        	//=>把每一次捕获的内容RES[0]存放到数组中
            ary.push(res[0]);
            //=>只要捕获的内容不为NULL,则继续捕获下去
            res = this.exec(str);
        }
        return ary.length === 0 ? null : ary;
    }
    RegExp.prototype.execAll = execAll;
}()

第二种:
let reg = /\d+/g;
console.log(reg.execAll("哈哈2019@2020嘿嘿"));
//=>字符串中的MATCH方法,可以在执行一次的情况下,捕获到所有匹配的数据(前提:正则也得设置G才可以)
console.log("哈哈2019@2020嘿嘿".match(reg));