美文网首页
javascript正则表达式 execAll的实现 ----

javascript正则表达式 execAll的实现 ----

作者: 成熟稳重的李先生 | 来源:发表于2019-10-16 01:09 被阅读0次

    正则的捕获

    实现正则捕获的方法

    • 正则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)
    }
    

    运行

    image.png
    所以,全局匹配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是字符串的方法

    相关文章

      网友评论

          本文标题:javascript正则表达式 execAll的实现 ----

          本文链接:https://www.haomeiwen.com/subject/tygemctx.html