1.正则 #

正则就是一种规则,用来处理字符串
1.判断一个字符串是否符合制定规则 test 匹配
2.把字符串中符合正则的内容捕获到 exec 捕获

1.1 创建正则的方式 #

1.字面量方式

var reg = /\d/;

2.实例创建

var reg = new RegExp("\d");

这两种创建方式的区别的

console.dir(RegExp.prototype);
var reg = /\d/;  //包含一个0-9的数字
reg.test(str)

1.2 元字符 #

每一个正则表达式都是由元字符和修饰符组成的
元字符:在两个斜杠之间有意义的字符就是元字符
修饰符:全局匹配g,不区分大小写i,行首行尾m

1.3 特殊意义字符 #

\ :转义字符,转义后边字符所代表的含义
^ :以某个元字符开始
$ :以某个元字符结尾
^和$并不占位,当同时出现时就表示一个字符
\n:匹配一个换行符
. :除了\n以外的任意字符

var reg = /^0.2$/;
//以0开头,以2结尾,中间为除了\n的任意字符

若想只表示0.2则需要对元字符进行转义

var reg = /^0\.2$/;

():分组,把一个大正则划分为几个小正则

x|y:x或y中的一个

\d:0-9之间的数字
\D:除了0-9之间的数字,以外的任意字符
\b:一个边界符
\w:数字、字母、下划线中的任意字符 等价于[0-9a-zA-Z_]
\s:匹配一个空白字符 如:空格,制表符(tab键),换页符

1.4 出现次数的量词元字符 #

"*" :出现0到多次
"+" :出现1到多次
"?" :出现0或1次
{n}:出现n次
{n,}:出现n到多次
{n,m}:出现n到m次

1.5 简单的手机号验证 #

有效数字验证: []中出现的所有字符都是代表本身意义的字符,没有特殊含义
[]中不识别两位数
()分组的作用:能改变x|y的默认优先级

var reg = /^18|19$/;
var reg2 = /^(18|19)$/;

1.6 字面量创建和实例创建的区别 #

字面量方式中斜杠之间包含的所有内容都是元字符,不能进行变量拼接

var name = "abc";
var reg = /^\d+"+name+"\d+$/;
console.log(reg.test('2015"""nameee"2016'));

实例创建方式中包含的就是字符串

var name = "abc";
var reg = new RegExp("^\\d+"+name+"\\d+$");
console.log(reg.test("2015abc2016"));
//在字符串中需要对\进行转义

1.7 正则实例 #

1.或者2-6或者8

var reg = /^[12-68]$/;

2.数字字母下划线和-

var reg = /^[\w-]$/;

3.匹配年龄18-65之间 分为18-19,20-59,60-65

var reg = /^(1[8-9]|[2-5]\d|6[0-5])$/;

4.匹配中国汉字姓名

var reg = /^[\u4e00-\u9fa5]{2,4}$/;

1.8 正则的捕获exec #

捕获的内容是一个数组[当前正则捕获到的内容为:index,捕获内容在字符串中起始索引;捕获的原始字符串]
若没有匹配到内容,则直接返回null
每一次捕获时都先进行默认匹配,如果没有匹配成功则返回null;只有有匹配的内容才能捕获到

var reg = /\d+/;
var str = "abcde2015fghijk2016";
var res = reg.exec(str);
console.log(res);

2. 正则捕获的特点 #

2.1 懒惰性 #

修饰符:g,i,m

var reg = /\d+/g;
var str = "abcde2015fghijk2016";

console.log(reg.lastIndex);//0
console.log(reg.exec(str));//["2015"...]
console.log(reg.lastIndex);//9
console.log(reg.exec(str));//["2016"...]

原理:增加全局修饰符g后,每一次捕获结束后lastIndex的值都变为了最新的值,下一次捕获从最新位置查找,这样就查找到了所有内容

var reg = /\d+/g;
var str = "abcde2015fghijk2016lmn2017";
var arr = [];
var res = reg.exec(str);
while(res){
  arr.push(res[0]);
  res = reg.exec(str);
}

2.2 贪婪性 #

正则的每一次捕获都是按照最长的匹配结果捕获的,例如:2,20,201,2015
如何解决贪婪性?
在量词元字符后加一个""?即可,例var reg = /\d?/g;

?作用:
1)放在普通元字符后面表示出现0或1次
2)放在量词元字符后面表示取消捕获时的贪婪性

字符串中的match方法,把所有和正则匹配的字符都获取到

var reg = /\d+?/g;
var str = "abcde2015fghijk2016lmn2017";
var arr = str.match(reg);

match存在的问题: 在分组捕获的情况下,match只能捕获到大正则匹配的内容,而对于小正则捕获的内容是无法获取的

2.3 分组捕获 #

1)改变优先级
2)分组引用

var reg = /^(\w)\1(\w)\2$/;
console.log(reg.test("zzff"));
console.log(reg.test("z0fa"));

\2代表和第二个分组出现一模一样的内容(值一样)
\1代表和第一个分组出现一模一样的内容
3)分组捕获
正则在捕获的时候,不仅把大正则匹配的内容捕获到,而且还可以把小分组匹配的内容捕获 "?:"在分组中只匹配不捕获

var reg = /^(\d{2})(\d{4})(\d{4})(\d{2})(\d{2})(?:\d{2})(\d)(?:\d|X)$/;
var str = "130180199210011234";
console.log(reg.exec(str));
console.log(str.match(reg));  //都能捕获到
var reg = /abc(\d+)/g;
var str = "abc123abc456abc789";
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));

console.log(str.match(reg));  //只能捕获大正则匹配内容

3.replace方法 #

replace(oldStr,newStr); 在不使用正则情况下,每使用一次只能替换一个字符

var str = "abcd2015abcd2016";
str.replace("abcd","abcde").replace("abcd","abcde");
console.log(str);
str.replace(/abcd/g,"abcde");

replace第一项查看正则原理 像exec一样,把所有匹配内容都捕获到,统一替换成目标字符串

str.replace(/abcd/g),function(){
  console.log("replace");
  return "abcde";
}

当第二个参数换为函数时,该匿名函数执行次数取决于正则捕获次数
函数参数:
1).arguments[0]:exec捕获数组的第一项;
2).arguments[1]:exex捕获数组的Index;
3).arguments[1]:exex捕获数组的input内容,即原始字符串;
4).若/(ab)(cd)/分组后,则不仅捕获大正则内容,还能捕获小分组内容.

每一次执行匿名函数时,里面传递的参数值arguments和通过exec捕获到的结果是类似的(即使正则有分组,也可以通过arguments获取到分组内容)

3.1 replace实战-汉字大写 #

var str = "2016"
var arr = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"];
str = str.replace(/\d/g,function(){
  return arr[arguments[0]];
})

3.2 replace实战-统计字符 #

//获取字符串中出现次数最多的字符
var str = "fgjkdsafsadfnakfbdsafgdafdsfffjdj";
//获取给一个字符出现的次数
var obj = {};
str.replace(/[a-z]/gi,function(){
  var val = arguments[0];
  if(obj[val] >= 1){
    obj[val] += 1;
  }else{
    obj[val] = 1;
  }
});
console.log(obj);
var max = 0;
for(var key in obj){
  obj[key] > max ? max = obj[key] : null;
}
var arr = [];
for(var key in obj){
  obj[key] === max ? arr.push(obj[key]) : null;
}
console.log(arr);

3.3 replace实战-模板替换 #

//模板引擎实现原理
var str = "My name is {0},my age is {1},and I come from {2}.My favorite is {3}.";
var arr = ["Amy",12,America,"cooking"];
str.replace(/(\d+)/g,function(){
  return arr[arguments[1]];
  //因为捕获的为小正则,所以为arguments[1]项
});
console.log(str);

3.4 replace实战-截取链接 #

//截取链接中的信息
    var str = 'https://mail.qq.com/cgi-bin/frame_html?sid=Xjf8ScPeUWP0Imcw&r=1ab0aea21033bf4164c1187edac80cfa';
    var reg = /([^?=&]+)=([^?=&]+)/g;
    var obj = {};
    var res = reg.exec(str);
    while(res){
        obj[res[1]] = res[2];
        res = reg.exec(str);
    }
    console.log(obj)

3.4 replace实战-时间转换 #

var str = "2016-7-26 16:30:3";
//2016年07月26日 16时30分03秒
var arr = [];
var reg0 = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2})$/g;
str.replace(reg0,function(){
    arr = [].slice.call(arguments);
    arr = arr.slice(1,7);
})
var resStr = "{0}年{1}月{2}日 {3}时{4}分{5}秒";
//var arr = ["2016","7","26","16","30","3"];
var reg = /{(\d+)}/g;
resStr = resStr.replace(reg,function(){
    var num = arguments[1];
    var val = arr[num];
    if(val<10){
        val = "0"+val;
    }
    return val;
})
console.log(resStr);