那些年我们一起走过的正则表达式的坑

一、为什么需要学习正则表达式

正则表达式是一种应用广,灵活度高的一种查找方式,目前在爬虫爬取,对特定的内容的抓包,登录的验证等多个方面都用得上正则表达式,正是因为其极高的灵活度,所以也会给我们的使用带来一定的麻烦,同时也提高了我们开发的复杂程度,复杂程度主要表现在语法上的不便记忆和应用层面上的易出错,今天我们就来谈谈正则表达式在应用层面上常出现的错误

二、正则表达式常见坑与注意点

1、零宽断言理解错误

零宽断言匹配的相当于是一个位置,不是一个具体的内容

示例:

将字符串str="test.com"的.前面的替换为1,也就是str="1.com"

错误示范:

    var str="test.com";
    console.log(str);
    var reg=/(?=\.)*/gi;
    //var re=new RegExp(reg);
    str=str.replace(reg,"1");
    console.log(str);

运行结果是:str="1t1e1s1t1.1c1o1m",我想此时你的心情一定是这样的

 从这个运行结果来看,就是在原来的字符串中的每个字符前面插入1,但是这个并不是我们所要求的,造成这样的原因主要是位置弄错了,现在把代码改为如下所示:

 

var str="test.com";
console.log(str);
var reg=/\w+(?=\.)/gi;
//var re=new RegExp(reg);
str=str.replace(reg,"1");
console.log(str);

 

这样运行一下就得到了我们所要求的,这个位置我们其实是要求:零宽断言+匹配类型+元字符+零宽断言,错误示范中是零宽断言+元字符这样的一种组合,根本不符合语法的要求,所以错误。但是里面除了匹配类型是一定要存在的,其余的都可以按要求省去,也就是说不是必须的

 2、后向调用理解错误

示例

匹配字符串str="455 33"

错误示范

var str="455 33";
var test=/\b([1-4]\d{1,2})\s?\1\b/gi;
console.log(test.test(str));

这个错误主要的原因是对后向调用的理解有误,后向调用第n次使用时匹配第一次的完全相同的内容,但是不意味着在这里第二次引用前面分组的正则表达式,所以这里只匹配“455 455”这样的字符串

 

对了这里里面的/g指的是全局匹配也就是在传入中的全部内容进行搜索,如果不设置的话那么就返回第一个匹配的内容,/i也就是忽略大小写的意思,除了这两个外还有/m,表示多行匹配,什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号

 3、全局变量的导向错误

这个错误不知道怎么说,但就是挺奇葩的,知道的人麻烦再下面留言一下

示例:

将.号前面的内容替换为"t",字符串为"dd1.432"

错误示范:

var str="dd1.432";
var reg=/\w*?(?=\.)/gi;
str=str.replace(reg,"t");
console.log(str);

 

 这个时候原本你会以为正确运行但是,出现的效果确实“tt.432”,顿时你的内心一定是跟博主一样有千万只草泥马在奔腾

但是最后的调试结果确实把最后面的g去掉,或者是修改为下面这样

var str="dd1.432";
var reg=/^\w*?(?=\.)/gi;
str=str.replace(reg,"t");
console.log(str);

 

4、对^ $理解上的错误

示例:

将上题修改为如下所示

错误示范:

var str="asdf dd1.432";
var reg=/^\w*?(?=\.)/gi;
str=str.replace(reg,"t");
console.log(str);

 

^匹配的是传入的字符串str的最开始的部分,$匹配的是str字符串最后的部分,如果是中间就不能使用这两个限定,还好这个坑,博主不曾踩过

5、获取某个DOM节点下面的内容

示例:

获取标签<ul>下面的内容,具体是str="<ul>  leslie</ul><ul>  谢灿勇</ul>"

 JavaScript代码

 

var str="<ul>  leslie</ul><ul>  谢灿勇</ul>";
var reg=/(?<=<ul>)[\s\S]*?(?=</ul>)/g;
str=str.replace(reg,"t");
console.log(str);

 

运行的结果是:

这里面为什么会出现这样的情况,相信此时你的内心也是奔溃的,犹如千万只草泥马呼啸而过

经过了大量的试验验证,发现竟然是由于JavaScript中的正则表达式支持的相对比较少,所以也就没有支持零宽度正回顾后发断言[(?<=<ul>)],而且里面还存在另外的一个错误就是“/”是需要进行转义操作的,但是这个时候我们发现要获取<ul>位置后面的内容好像没有方法可以实现了,经过了思考,我选择了多次匹配来实现

6、多次匹配

接上面的问题继续说下,我们所说的多次匹配其实就是第一次就只实现一部分,第二层次再实现一部分,这样一直下去,直到完成。

我们第一次就只实现将</ul>去掉,然后将<ul>去掉,这样就得到我们所要求的

 

var str="<ul>    leslie </ul><ul>  xiecanyong</ul>";
var reg=/<ul>[\s\S]*?(?=<\/ul>)/gi;
str=str.match(reg);
var reg1=/<ul>/i;
for(var i=0,max=str.length;i<max;i++){
    str=str.replace(reg1," ");
console.log(str);

}

 

第一次实现的代码是这样的,但是一运行却发现只打印出leslie,这里主要的原因是,第一次就将leslie存入str变量中,然后第二次调用时,str=“leslie”,所以根本获取不到<ul>,所以根本就是为空,所以也就只匹配到leslie,将代码修改为如下就可以正常运行了

 

var str="<ul>    leslie </ul><ul>  xiecanyong</ul>";
var reg=/<ul>[\s\S]*?(?=<\/ul>)/gi;
str=str.match(reg);
var reg1=/<ul>/i;
for(var i=0,max=str.length;i<max;i++){
    str[i]=str[i].replace(reg1," ");
console.log(str[i]);
}

 

 打印一下结果:

 好的问题完成了,哈哈,内心如释重负

7、多次匹配实现思路

其实在上面的内容中已经实现了两种常见的多次匹配的思想,一种是获取我们所要求的[str=str.match(reg)],另一种是将我们要除去的东西替换为空[ str[i]=str[i].replace(reg1," ")]所示

 三、总结

 通过这篇文章主要是希望大家能够学习到一些在JavaScript中你可能会遇到的一些坑,以及一些问题的实现思路,如果在这里有什么地方说错的,欢迎大家帮忙指正,在此不胜感激,如果你觉得这篇文章对你有帮助的话请为我点一个赞,你的点赞是我前进的动力。后续如果是大家有什么问题的话,也欢迎大家留言共同探讨

posted @ 2016-03-20 23:10  热衷理财的技术渣渣  阅读(2408)  评论(1编辑  收藏  举报