正则

元字符

[拥有特殊含义的元字符]

\d -> 匹配一个0-9的数字,相当于[0-9],和它相反的是\D ->匹配一个除了0-9的任意字符
\w -> 匹配一个0-9、a-z、A-Z、_的数字或字符,相当于[0-9a-zA-Z_]
\s -> 匹配一个空白字符(空格、制表符...)
\b -> 匹配一个单词的边界
\t -> 匹配一个制表符
\n -> 匹配一个换行
. -> 匹配一个除了\n以外的任意字符
^ -> 以某一个元字符开头
$ -> 以某一个元字符结尾
\ -> 转移字符
x|y -> x或者y的一个
[xyz] -> x、y、z中的任意一个
[^xyz] -> 除了xyz中的任意一个字符
[a-z] -> 匹配a-z中的任意一个字符
[^a-z] -> 匹配除了a-z中的任意一个字符
() -> 正则中的分组

注意:
1)关于[]
a、[+] ->中括号中出现的所有字符都代表的是本身的意思
b、[12-65] ->这个不是12-65而是1/2-6/5三者中的一个

  1. 关于()
 a、分组的作用是改变默认的优先级,例如:/^18|19$/,1811891198191819...都符合,而不是我们认为的1819,但是改成/^(18|19)$/就是单纯的1819了
 b、可以在捕获大正则匹配的内容同时,把分组匹配的内容也进行捕获->分组捕获
 c、分组引用,例如:/^(\d)(\w)\2\1$/,这里的\2是和第二个分组出现一模样的内容,\1是和第一个分组出现一模一样的内容,例如:"0aa0"就符合了
 
[代表数量的量词元字符]

* -> 0到多个
+ -> 1到多个
? -> 01{n} -> 出现n次
{n,} -> 出现n到多次
{n,m} -> 出现n到m次

注意:
1)关于?的几种情况
 a、放在非量词元字符后面,代表出现0-1次
 b、放在量词元字符后面,代表取消捕获时候的贪婪性,例如:reg=/\d+/; reg.exec("2015") -> "2015" 但是如果正则这样写 reg=/\d+?/; reg.exec("2015") -> "2"
 c、在分组开头加?:,代表当前的分组只是匹配不进行捕获,例如:/^(?:\d+)$/
 d、在分组开头加?=,正向预查,例如:/^zhufeng(?=1|2)$/ 只有"zhufeng1""zhufeng2"才符合
 e、在分组开头加?!,负向预查,例如:/^zhufeng(?!1|2)$/ 除了"zhufeng1""zhufeng2"不符合,其他的只要是"zhufeng(任何的东西)"都符合

[代表本身意思的元字符]
除了以上的,在字面量方式中,我们出现的其他任意字符代表的都是自己本身的意思
var num=12;
var reg=/^\w"+num+"$/; ->这里"+num+"不是把变量的值拼接,而这里的不管是"还是+都是元字符
->对于需要拼接字符串和变量的方式我们只能使用实例方式创建正则

修饰符

 i -> ignoreCase 忽略字母的大小写
 g -> global 全局匹配 (加上g可以解决正则捕获时候的懒惰性)
 m -> multiline 多行匹配

项目中常用的正则

 1)有效数字的
 var reg=/^[+-]?(\d|([1-9]\d+))(\.\d+)?$/;

 2)邮箱的
 var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;

 3)电话的
 var reg = /^1\d{10}$/;

 4)年龄在18-65之间的
 var reg = /^((18|19)|([2-5]\d)|(6[0-5]))$/;

 5)中文姓名
 var reg = /^[\u4e00-\u9fa5]{2,4}$/;

 6)身份证
 var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(?:\d{2})(\d)(?:\d|X)$/;
 //-> 130828(省市县) 1990(年) 12(月) 04(日) 06 1(奇数是男偶数是女) 7(数字或者X)

正则的匹配

reg.test([string]) ->true就是匹配成功 false->匹配不成功

正则的捕获

 1、exec:正则的捕获方法 ->先匹配,然后把匹配的内容进行捕获
   1)如果字符串没有匹配这个正则,捕获的结果是null
   2)如果和正则匹配,返回的结果是一个数组
   ["2015", index: 7, input: "zhufeng2015peixun2016"]
   第一项是我们捕获的内容
   index:捕获的内容在元字符串中开始的索引位置
   input:捕获的原始字符串

   2、正则的捕获是懒惰的
   原理:正则的每一次捕获都从lastIndex值开始,第一次捕获的时候,lastIndex=0,从原始字符串索引为0的位置开始查找捕获;而默认的情况下,第一次捕获完成,lastIndex的值并没有发生改变,还是0,所以第二次捕获还是从原始字符串索引为0处开始查找,这样找到的还是第一次捕获的内容...
   解决办法:添加全局修饰符g ->加上g后,第一捕获完成后,lastIndex值发生了改变,变为第一次捕获内容后的第一个字符的开始索引,第二次捕获是继续向后查找的...
   疑问:我不用全局修饰符g,每一次捕获完成手动的修改lastIndex值行吗? ->不行,虽然手动的修改lastIndex,确实把lastIndex进行改变了,但是正则查找的时候还是从索引0开始的
   var str = "zhufeng2015peixun2016";
   var reg = /\d+/g;

   为了防止没有加全局修饰符g导致的死循环,我们在处理之前,对于没有添加g的手动给添加一个g
   RegExp.prototype.myExecAll = function myExecAll() {
       var _this = this, str = arguments[0], ary = [], res = null;
       !_this.global ? _this = eval(_this.toString() + "g") : null;
       res = _this.exec(str);
       while (res) {
           ary[ary.length] = res[0];
           res = _this.exec(str);
       }
       return ary;
   };
      console.log(reg.lastIndex);//->0
      var res = reg.exec(str);
      console.log(res);

      console.log(reg.lastIndex);//->11
      res = reg.exec(str);
      console.log(res);

      console.log(reg.lastIndex);//->21
      res = reg.exec(str);
      console.log(res);//->null

   3、字符串中存在一个叫做match的方法也可以实现捕获,而且只要我们取消了正则的懒惰型,执行一次match方法就可以捕获到所有的内容了
   var str = "zhufeng2015peixun2016";
   var reg = /\d+/g;
   console.log(str.match(reg));
   疑问:那我们都用match来替换exec多好啊?

   4、正则的分组捕获
   每一次捕获的时候,不仅仅可以把大正则匹配的内容捕获到,而且还可以把每一个小分组(子正则)匹配的内容单独的捕获到
      var str = "zhufeng[2015]peixun[2016]";
      var reg = /\[(\d)(\d+)\]/g;
      var res = reg.exec(str);
      console.log(res);
      ["[2015]", "2", "015", index: 7, input: "zhufeng[2015]peixun[2016]"]
      数组中的第一项是大正则捕获的内容 res[0]
      数组中的第二项是第一个分组捕获的内容 res[1]
      数组中的第三项是第二个分组捕获的内容 res[2]
      ....

   分组的只匹配不捕获:我们如果执行把分组内容进行匹配但是不进行捕获的话,只需要在分组的前面加上?:即可
      var str = "zhufeng[2015]peixun[2016]";
      var reg = /\[(?:\d)(\d+)\]/g;
      var res = reg.exec(str);
      console.log(res);
      ["[2015]", "015"...]
      数组中的第一项是大正则捕获的内容 res[0]
      数组中的第二项是第二个分组捕获的内容 res[1]
      第一个分组添加了?:,所以只匹配不捕获

   5、match和exec的区别:
   match只能捕获到大正则匹配的内容,对于有分组的情况下,不能捕获分组的内容;所以,如果捕获的时候不需要捕获分组的内容,我们直接的使用match更加的方便,如果需要捕获分组的内容,我们只能使用exec来一个个的捕获
      var str = "zhufeng[2015]peixun[2016]";
      var reg = /\[(\d+)\]/g;
      //console.log(str.match(reg));//->["[2015]", "[2016]"]
      var ary = [];
      var res = reg.exec(str);
      while (res) {
          //ary.push(res[1]);
          ary.push(RegExp.$1);//RegExp.$1获取当前正则第一个分组捕获的内容(可能在部分IE浏览器中获取不到值)
          res = reg.exec(str);
      }
      console.log(ary);

   6、正则的贪婪性:在每一次捕获的时候,总是按照正则匹配的最长结果捕获
      var str = "zhufeng2015peixun2016";
      var reg = /\d+/g;
      console.log(reg.myExecAll(str));//-->["2015","2016"]
   var str = "zhufeng2015peixun2016";
   var reg = /\d+?/g;
   console.log(reg.myExecAll(str));//-->["2", "0", "1", "5", "2", "0", "1", "6"]

   7、分组引用
   \2代表出现和第二个分组一模一样的内容
   \1代表出现和第一个分组一幕一样的内容
   var reg=/^(\w)(\w)\2\1$/;
   "woow""1221"...

   8、字符串方法->replace:把一个字符串中的某个字符串替换成新的内容
   [在不使用正则的情况下]
   每一次执行只能替换一个,需要替换多个,同样需要执行多次
   var str = "zhufeng2015 zhufeng2016";
   "zhufeng" -> "珠峰"
   str = str.replace("zhufeng", "珠峰").replace("zhufeng", "珠峰");

   有些时候即使执行多次,也实现不了替换
   "zhufeng" -> "zhufengpeixun"
   str = str.replace("zhufeng", "zhufengpeixun").replace("zhufeng", "zhufengpeixun");

   [第一个参数可以是一个正则] 把所有和正则匹配的内容进行替换(但是和捕获一样默认是懒惰的,只有加上全局修饰符g才可以)
      var str = "zhufeng2015 zhufeng2016";
      str = str.replace(/zhufeng/g, "zhufengpeixun");
      console.log(str);

   1)执行和执行次数问题
   其实和exec捕获的原理是一模一样的
   例如:我们第二个参数如果传递的是一个函数,每当正则在字符串中捕获一次当前的这个函数就执行一次 ->本题中一共捕获了两次,所以函数执行了两次
   var str = "zhufeng2015 zhufeng2016";
   str = str.replace(/zhufeng/g, function () {
       2)参数问题
       console.dir(arguments);
       不仅仅是执行function,而且还给我们的函数传递了参数,并且传递的参数和每一次exec捕获的内容是一模一样的
       如果是第一次exec捕获->["zhufeng",index:0,input:"原始字符串"]
       第一次执行函数里面的参数
       arguments[0] -> "zhufeng"/**/
       arguments[1] -> 0  相当于exec中的index 开始捕获的索引位置
       arguments[2] -> "原始字符串" 相当于exec中的input

       3)返回值问题
       return返回的是什么,就相当于把当前捕获的内容替换成什么
       return "zhufengpeixun";
   });

实战

1、获取一个字符串中出现次数最多的字符和对应的次数,例如:var str = "zhufengpeixun2015yangfanqihang";问哪几个字符出现的次数最多,一共有多少次?
   var str = "zhufengpeixun2015yangfanqihang", obj = {};
   //首先统计每一个字符出现的次数
   str.replace(/\w/g, function () {
       var key = arguments[0];
       if (obj[key] >= 1) {
           obj[key]++;
           return;
       }
       obj[key] = 1;
   });
   //用假设法获取出现的最多次数
   var maxNum = 0;
   for (var key in obj) {
       if (obj.hasOwnProperty(key)) {
           obj[key] > maxNum ? maxNum = obj[key] : null;
       }
   }
   //最后在把所有出现次数为maxNum的输出
   var res = "最多出现:" + maxNum + "次  出现的字符是:";
   for (key in obj) {
       if (obj.hasOwnProperty(key)) {
           obj[key] === maxNum ? res += key + " " : null;
       }
   }
   obj = null;
   console.log(res);


   2、模板引擎绑定数据实现的原理
   //->"my name is 葛琪,my age is 26,i com from china,i can do javascript~~";
   var ary = ["葛琪", "26", "china", "javascript"];
   str = "my name is {0},my age is {1},i com from {2},i can do {3}~~";
   str = str.replace(/\{(\d+)\}/g, function () {
       return ary[arguments[1]];
   });
   console.log(str);


   3、单词首字母大写
   str = "my name is zhou xiao tian,my age is twenty five years old~~";
   str = str.replace(/\w+/g, function () {
       var res = arguments[0];
       return res.substr(0, 1).toUpperCase() + res.substr(1);
   });
   console.log(str);


   4、格式化时间
   ->"2015年05月03日 12时09分13秒"

      str = "2015-05-03 12:09:13";
      str = str.replace(/^(\d+)-(\d+)-(\d+) +(\d+):(\d+):(\d+)$/, "$1年$2月$3日 $4时$5分$6秒");
      console.log(str);
   String.prototype.myFormatTime = function myFormatTime() {
       var reg = /^(\d{4})(?:-|\/|\.|:)(\d{1,2})(?:-|\/|\.|:)(\d{1,2})(?:\s+)(\d{1,2})(?:-|\/|\.|:)(\d{1,2})(?:-|\/|\.|:)(\d{1,2})$/g, ary = [];
       this.replace(reg, function () {
           ary = Array.prototype.slice.call(arguments, 1, 7);
       });
       var format = arguments[0] || "{0}年{1}月{2}日 {3}:{4}:{5}";
       return format.replace(/{(\d+)}/g, function () {
           var val = ary[arguments[1]];
           return val.length === 1 ? "0" + val : val;
       });
   };
   str = "2015-5-3 12:9:13";
   console.log(str.myFormatTime());
   console.log(str.myFormatTime("{0}年{1}月{2}日"));
   console.log(str.myFormatTime("{1}-{2} {3}:{4}"));

   5、数字转大写
   //->"贰零壹伍"
   str = "2015";
   ary = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
   str = str.replace(/\d+?/g, function () {
       return ary[arguments[0]];
   });
   console.log(str);

   6、queryURLParameter 获取地址栏中的参数
   ->http://kbs.sports.qq.com/kbsweb/game.htm?mid=1467588&age=18
   ->{mid:"1467588",age:18}
   String.prototype.queryURLParameter = function queryURLParameter() {
       var reg = /([^?&=]+)=([^?&=]+)/g, obj = {};
       this.replace(reg, function () {
           obj[arguments[1]] = arguments[2];
       });
      var res = reg.exec(this);
      while (res) {
          obj[RegExp.$1] = RegExp.$2;
          res = reg.exec(this)
      }
       return obj;
   };
   var url = window.location.href;//获取当前页面的地址,下面我们假设一个地址,来看一下方法编写的正确性
   url = "http://kbs.sports.qq.com/kbsweb/game.htm?mid=1467588&age=18";
   console.log(url.queryURLParameter());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值