正则基础

正则又名火星文,在地球表面已经生存了好几百年了,主要的作用是来玩字符串的,字符串对它服服帖帖,制定一些规则,来操作(校验/匹配,捕获)字符串

  • 校验:reg.test(字符串) /^2\d{2}/.test(xml.status)

  • 捕获:

    • str.match(reg):字符串的方法,返回一个符合正则规则的数组 splite() search()
    • str.replace(reg,xxxxx):字符串的方法,里面的参数可以是一个正则的表达式,还可以加一个函数:str.replce(reg,function(){}),其作用巨大。
    • reg.exec(str):正则的方法
  • 创建正则的方法

    • 字面量形式:var reg=/^2\d{2}/
    • 对象实例创建:var reg=new RegExp()
    • 这两种方法创建的区别:字面量创建无法实现变量拼接,实例创建可以实现变量的拼接;字面量创建不需要转义,实例对象创建需要转义;var reg1=/^2\d{2}$/;//字面量方式创建,不需要转义;var reg2=new RegExp('^2\\d{2}$');//实例创建需要转义
  • 正则的组成

    • 元字符:就是包含在两个斜杠之间\元字符\的字符
      • \:转义;|:或;():分组;.:除了\n以外的其他字符;\n:换行;\b:开头结尾和空格;^:开头;$:结尾;\s:空格;\d:数字;\w:字母,数字和下划线;\S:不是空格;\D:不是数字;\W:不是数字,字母,下划线;[a-z]:字母从a到z中的一个或者多个,只要这个字符串里面包含a到z的字母就行:或;[^a-z]:不包含字母a到z中的任何一个;[abc]:abc中的一个;[^abc]:不包含abc中的任何一个或者全部,但是当有一个不是其中的字符就可以通过校验;
      • 量词元字符:*:0到多;+:1到多;?:0或1;{n}:正好n次;{n,}:最少n次,n到多次;{n,m}:n次到m次;
    • 修饰符:斜杠外面的 /^2\{d}/g
      • g:全局
      • m:换行
      • i:忽略大小写

注意点

  • ()小括号的用法:

    1. 提高优先级 /^(18|19)$/

    2. 分组的作用,这个作用巨大,使用str.replace(reg)的时候,会把那个小括号里面匹配的单独提出来

    3. 只匹配不捕获(?:\d+)

                     var str='icessun2017';
                     var reg=/icessun(\d+)/;
                     console.log(reg.exec(str));
                     // 当我们没有加入`?:`的时候,会把小分组里面的字符匹        配出来`["icessun2017", "2017", index: 0, input: "icessun2017"]`,但是加了以后,就只捕获str的全部,而小分组不会被捕获`["icessun2017", index: 0, input: "yuanmeng123"]`
      
  • []中括号的用法:

    1. 中括号中不会出现两位数
    2. 像类似于.-的,在中括号里面没有特殊的作用
  • ?问号的用法:

    1. 表示可有可无
    2. 解决正则捕获的贪婪性
  • 在中括号[]里面^表示不属于:[^a]

正则的捕获

  • 主要有三个方法
    • exec():reg.exec(str)
      • 正则的方法,每次调用的时候只能取到符合规则的一个值;
      • 返回的结果是个数组,默认情况下,这个数组包含3项
        • 符合大正则(reg)的内容
        • index:找到符号规则的字符串的索引
        • input:原始的字符串
      • 要是大正则里面存在小分组()的情况,小分组里面匹配的字符串内容在返回数组的第二项开始,返回的数组长度也因此增加。
    • match():str.match(reg) 功能强大
      - 字符串的方法,每次都能得到所有符合正则的内容,并且以一个新数组的形式返回
    • execmatch的区别:
      • 前者每次只能拿到一个值,后者可以拿到所有的值,并且其值是以新数组的形式返回
      • 前者里面可以拿到小分组,后面的只能拿到大正则,不能取到小分组
    • replace():str.replace(reg,xxxx)
      • 一般传入两个参数:正则规则和替换成的数据(当然可以是一个匿名函数,这个函数里面经过一些操作,返回我们要替换成的数据)str.replace(reg,'')或者str.replace(reg,function(){})
      • 我们想知道这个匿名函数里面传入了什么参数,可以直接在里面打印console.log(arguments)//arguments是用来接收实参的,打印出来,我们会发现,这个匿名函数接收三个参数:item,index,input,分别表示:与正则匹配的字符串,与正则匹配的字符串出现的索引位置,原始字符串str
      • 要是正则里面有小分组,arguments的长度会扩大,其回调函数中的参数实现跟exec()一样
  • 两大特点:
    • 懒惰性(在不加全局g的时候,一直是从字符串的开头找起)
      • 解决办法:给正则添加一个全局的g
      • 添加了全局的g会影响到lastIndex属性(从你找到第一次匹配正则规则的下一个字符开始查找接着匹配规则的字符串的索引值)
    • 贪婪性(会把所有匹配的一下子全部找出来)
      • 解决办法:在量词元字符后面加上+?

正则校验

  • 年龄在18到65岁之间:(重要)
首先我们要进行拆分:(18 19)(20---59)(60 65)分成三组

var reg=/^((18|19)|([2-5]\d)|(6[0-5]))$/

18或者19岁:reg=/^(18|19)$/

  • 中文的字符编码:\u4e00-\u9fa5
  • 邮箱验证:/^([\w.-]+)@([a-zA-Z0-9]+)((\.[a-zA-Z]{2,4}){1,2})$/
  • 有效数字的验证:/^[+-]?((\d|([1-9]\d+))(\.\d+)?)$/

replace()的应用

  • 敏感词过滤:匿名函数的第一个参数的应用

    • 制定一个敏感词的规则,获取其匹配字符串的长度与*拼接字符串
    var reg=/(艹|傻逼)/g;
    str.replace(reg,function($0){
         var str1='';
         for(var i=0;i<$0.length;i++){
                str1+='*';
          }
          return str1;
      })
    
  • 统计字符串中出现次数最多的单词和次数

    • 思路一:利用对象不重名的特性;然后假设其一个为最大值,进行比较;最后字符串拼接
    • 思路二:先字符串排序:字符串转数组str.split(''),把连续的字符串转成一个个的字符,并以数组的方式返回----数组排序str.sort(function(a,b){return a.localeCompare(b)})----数组转字符串ary.join(''),可以把一个个的字符转成连续的字符串;然后假设法+重复子项
    var str='aabbaAaCbbbbbAABBBBBAACCCC'
      //第一种:利用对象不重名的特性,
      // 把所有的字母以及其出现的次数用键值对保存在obj的对象里面
         var obj={}
         for(var i=0;imax){
                max=obj[attr];
               }
           }
       console.log(max);




   // 第二种方法:字符串转数组str.split('');数组的ary.sort()排序:汉字的比较排序a.localeCompare(b):这样才能不区分大小写;数组转字符串:str.join('')
     str=str.split('').sort(function(a,b){return a.localeCompare(b)}).join('');
  //次数  和  最多次数的字符 
  var max=0,strMax='';
  ///(\w)\1+/gi  重复子项
  str.replace(/(\w)\1+/gi,function($0,$1){
            if($0.length>max){//假设法
               max=$0.length;//出现的次数
               strMax=$1;   //出现次数最多的字符
             }else if($0.length==max){
                strMax+=$1;
              }

      });

  • 重复子项:/\w(\w)\1+/:这个匹配:abbb等类似的字符串

    • (\w):表示一个小分组 \1 表示和这个小分组一样 + 表示后面有多个一样的
    • /\w(\w)\1+(\w)\2/:\1 表示跟第一个小分组一模一样 \2 表示跟第二个小分组一模一样
  • url地址解析:把链接里面传入的参数以一个对象的形式(键值对)返回

     var str='http://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false';
     //把链接传给后台的参数,以一个新对象的形式返回,把这个方法放在String的原型上面,作为一个公共的方法
     String.prototype.urlParse=function(){
           var reg=/([^?&=]+)=([^?&=]+)/g;//在等号的左边和右边不包含?& =
      var obj={}
      //replace()函数里面的参数是依次传递的,所以必须是从第一个参数传递开始 有小分组,$1 $2 表示小分组匹配的内容;谁调用这个方法,this就指向谁
      this.replace(reg,function($0,$1,$2){
            obj[$1]=$2
      });
       }     
    
  • 日期格式化重点
var str='2017/05/05 11:59:30';

// 第一步:首先把str转成数组,目的也是拿到数组,方法有三种 1. 使用正则严格匹配 2. 使用字符串的match()方法 3. 使用字符串的split()方法
/**1. 使用正则严格匹配**/
var reg=/^(\d{4})[/-](\d{2})[/-](\d{2}) (\d{2}):(\d{2}):(\d{2})$/

var ary=null;

str.replace(reg,function(){
 ary=Array.prototype.slice.call(arguments,1,arguments.length-2);// 使用数组的slice方法,包前不包后,截取我们需要的匹配小分组数据,放到数组里面
});

/**2. 使用字符串的match()方法**/
var ary=str.match(/\d+/g);

/**3. 使用字符串的split()方法,拆分不是数字的符号**/
var ary=str.split(/[^\d]+/g)

// 第二步 替换成模版的样式

/**给你一个模版,按照其样式添加数据**/
var strTemplate='{0}年{1}月{2}日 {3}时{4}分{5}秒';

strTemplate=strTemplate.replace(/{(\d)}/g,function($0,$1){ return ary[$1]; });


//最后把上面的方法进行 封装

String.prototype.formatDate=function(template){
     // 要是传入了模版,就用传入的模版,没有就使用自己定义的模版
     template=template||'{0}年{1}月{2}日 {3}时{4}分{5}秒'
     //拿到数组
     var ary=this.match(/\d+/g);
     template=template.replace(/{(\d)}/g,function($0,$1){
          return ary[$1];
  });
  return template;
};
var res=str.formateDate('{3}时{4}分{5}秒');

  • 模版替换

//模版:
var str='my name is {0},i come form {1},my age is {2}';
//替换的内容:
var ary=['icessun','beijing',18];
//想把str中的{*}替换掉,还想用到*代表的数字0,1,2
str=str.replace(/{(\d)}/g,function($0,$1){
// 把$1 当作索引使用 $1表示的是小分组匹配的数据
 return ary[$1]});

//把str里面的数字替换成汉字的数字
var str='全日制第七期学费:18800';
var ary=['零','壹','贰','叁','肆','伍','陆','柒','捌','玖'];
// $0 表示匹配的数字 返回数组里面对应的数字去替换匹配的数字
str=str.replace(/\d/g,function($0){ return ary[$0]})


正则的静态属性

静态属性:类身上的私有属性-----把构造函数自己当作一个对象,是对象那就可以添加属性和方法(RegExp.$1;$1表示第一个小分组,$2表示第二个小分组 。。。。
实例上面的属性:分为公有属性(原型上面的属性)和私有属性(this.属性)
reg.lastIndex表示从那个位置开始匹配字符的

var str='alpha(opacity=10)';
var reg=/alpha\(opacity=(\d+)\)/g;
if(reg.test(str)){
    console.log(reg.lastIndex)//正则实例上面的属性
    console.log(RegExp.$1)//正则类上面的私有属性,静态属性
}
  • 去掉首尾空格
  var reg=/\w(\w)(\w)/;
  if(reg.test('abc')){
       console.log(RegExp.$1);//输出 b 对应的第一个分组的匹配字符
        console.log(RegExp.$2);// 输出 c 对应的第二个分组匹配字符
  }

  var str='    abc     kjf      ';
  //以空格开头的或者以空格结尾的  要是想出掉全部的空格:/\s+/g;
  str=str.replace(/(^\s+|\s+$)/g,'');
  console.log('('+str+')'); //(abc     kjf)

面试题

请使用exec来实现match
考察的知识点:原型,this指向,正则
思考的思路:

  1. match是谁的方法(String),放在哪里?(公共的方法,原型prototype上面)
  2. String.prototype.match中的this是谁(谁调用match方法,this就指向谁)
  3. exec来实现match,exec是正则的方法
  • js代码:
//需求:找到字符串str中的所有的数字,并且返回一个数组
var str='icessun2017zhanwang2018huigu2016';

var reg=/\d+/g;

//想要在match里面使用exec来实现match的功能,那么就要传入一个正则reg,这样才能使用exec方法
String.prototype.match=function(reg){
     //1 先拿到第一次的exec的返回值,this指向字符串str,谁调用这个函数,函数里面的this就指向谁
     var res=reg.exec(this);

     var ary=[];

     //2 通过while循环依次向数组里面放入我们找到的值

      while(res){
             ary.push(res[0]);
             //因为exec每次只能找到一个匹配的数据,所以多次执行
             res=res.exec(this);
      }
 
      // 3 返回数组
      return ary;
}
str.match(reg);

你可能感兴趣的:(正则基础)