珠峰培训

js中正则捕获特点及replace方法

作者:jw

2016-08-14 23:24:02

300

1. 正则捕获的特点

1.1 懒惰性

  • 每次执行exec只捕获一个匹配内容,在不进行任何处理的情况下再执行多次捕获,还是捕获第一个匹配内容

  • 正则属性lastIndex:正则每一次捕获在字符串中开始查找的位置,默认值为0

  • 解决懒惰性:在正则的末尾正价修饰符”g”

修饰符:g,i,m

  • g:global全局匹配

  • i:ignoreCase忽略大小写匹配

  • m:multiline多行匹配

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);
}

1.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只能捕获到大正则匹配的内容,而对于小正则捕获的内容是无法获取的

1.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)); //只能捕获大正则匹配内容

2.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获取到分组内容)

  • return的含义是返回的结果,相当于大正则捕获的内容被替换为返回内容;

  • 不写return的话则返回undefined,以undefined为内容进行替换。

2.1 replace实战-汉字大写

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

2.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);

2.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);

2.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)

2.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);