正则的捕获

133 阅读5分钟
  • 正则RegExp.prototype上的方法

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

    • exec

      基于exec实现正则的捕获:

      • 捕获到的结果是null或者一个数组

        第一项:本次捕获到的内容

        其余项:对应小分组本次单独捕获的内容

        index:当前捕获内容再字符串中的起使索引

        input:原始字符串

      • 每执行依次exec,只能捕获到一个符合正则规则的,但是默认情况下,执行多变,获取的结果永远都是第一位匹配到的,其余捕获不到;

        这就是正则的懒惰性,默认值捕获第一个;

      let str = "zhangsan1789522addff13";
      let reg = /\d+/;
      //reg.lastIndex  当前正则下一次匹配的起使索引位置
      console.log(reg.lastIndex);//0  匹配捕获的是从str的索引0的位置开始寻找的
      console.log(reg.exec(str));
      //0 第一次匹配捕获的,lastIndex没有改变,所以下一次依然是从字符串最开始部分开始寻找,找到的始终是第一个匹配到的结果
      console.log(reg.lastIndex);
      ​
      let str = "zhangsan1789522addff13";
      //设置全局匹配
      let reg = /\d+/g;
      //reg.lastIndex  当前正则下一次匹配的起使索引位置
      //0  匹配捕获的是从str的索引0的位置开始寻找的
      console.log(reg.lastIndex);
      console.log(reg.exec(str));//['1789522',
      //15 设置全局匹配之后,
      //第一次匹配捕获的,lastIndex会自动修改,
      //所以下一次依然是从字符串最开始部分开始寻找,找到的始终是第一个匹配到的结果
      console.log(reg.lastIndex);//15
      console.log(reg.exec(str));//['13
      console.log(reg.lastIndex);//22
      //当全部捕获之后,再次捕获的结果是null,但是lastIndex又回归了初始值0,又从第一个开始捕获,循环开始
      console.log(reg.exec(str));//null//编写方法execAll,执行一次把所有匹配的结果都捕获到
          //前提:正则一定要设置全局修饰符g
          ~ function (){
              function execAll(str){
                  //判断当前正则是否是加了全局捕获
                  if(!this.global) return this.exec(str);
                  //str:要匹配的字符串
                  //this:RegExp的实例(当前操作的正则)
                  //ary :存储y最后所有的捕获信息,res存储每一次捕获的信息
                  let ary = [],y
                      res = this.exec(str);
                  while(res){
                      //把每一次捕获的内容res[0]存放到数组中
                      ary.push(res[0]);
                      //只要捕获的内容不为null,则继续捕获下去
                      res = this.exec(str);
                  }
                  return ary;
              }
              RegExp.prototype.execAll = execAll;
          }();
      ​
          let str = "zhangsan1789522addff13";
          //设置全局匹配
          let reg = /\d+/g;
          console.log(reg.execAll(str));
      
    • test

      用于检测一个字符串是否匹配某个模式;

      返回值:如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。

      test()继承正则表达式的lastIndex属性,表达式在匹配全局标志g的时候须注意。

  • 字符串string.prototype上支持正则表达式处理的方法

    • replace:

      replace()方法返回一个由替换值(replacement)替换部分或所有的模式(pattern)匹配项后的新字符串。方法接受两个参数:要替换的字符串以及将替换为的字符串。第1个参数可以是一个普通的字符串或是一个正则表达式

      第2个参数可以是一个普通的字符串或是一个回调函数

      如果第1个参数是RegExp, JS会先提取RegExp匹配出的结果,然后用第2个参数逐一替换匹配出的结果

      如果第2个参数是回调函数,每匹配到一个结果就回调一次,每次回调都会传递以下参数:

      result:本次匹配的结果;

      $1,.....正则表达式中有几个()就会传递几个参数,分别代表提取的结果,最多9个

      offset:记录本次匹配的开始位置

      source:接受匹配的原始字符

      //实现字符串的trim函数,去除字符串两边的空格
      String.prototype.trim = function(){
          //1、匹配到的方式用""替换
          return this.replace(/(^\s+)|(\s+$)/g,function(){
              return "";
          });
          
          //2、^\s+ 表示以空格开头的连续空白字符,\s+$ 表示以空格结尾的连续空白字符
          return this.replace(/(^\s+)|(\s+$)/g,'');
      }
      ​
      //提取浏览器url参数名和参数值,
      function getUrlParamObj(){
          let obj = {},
              params = window.location.search.substr(1);
          //([^&=]+)=([^&=]*)/gi 每次匹配到的都是一个完整key/value
          params.replace(/([^&=]+)=([^&=]*)/gi,function (rs,$1,$2){
              obj[$1]=$2;
          })
          return obj;
      }
      //字符串指定位置插入
      String.prototype.insetAt = function(str,offset){
          return this.replace(new RegExp("(.{"+offset+"})"),"$1"+str);
      }
      
    • match:match方法的返回值是存放首次匹配内容的数组。如果没有找到匹配结果,返回null。

      (1).如果不存在匹配的子字符串,返回null。 (2).如果存在匹配的子字符串,返回一个数组。

      (1).第0个元素是匹配结果。 (2).第1个元素是第一个引用型分组匹配的子字符串。 (3).第2个元素存放的是第二个引用型分组匹配的子字符串,依次类推。

      返回的数组对象同时具有两个属性: (1).index:返回匹配的子字符串起始字符在stringObject源字符串中的位置。 (2).input:返回stringObject源字符串。

    • splite:可以将字符串拆分为与确切字符或模式匹配的子字符串

      注意,与 i 标记和其他标记不同,全局标记 g 在 split中是无关紧要的。这是因为 split 在与正则表达式匹配的几个位置拆分了字符串。

  • 正则的分组捕获

    • 第一项:大正则匹配的结果
    • 其余项:每一个小分组单独匹配捕获的结果
    • 如果设置了分组(改变优先级),但是捕获的时候不需要单独捕获,可以基于?:来处理;
    • 既要捕获到{数字},也想把单独的数字捕获到,例如,{0}还需要单独获取0的时候,可以使用分组;