一、为什么需要学习正则表达式
正则表达式是一种应用广,灵活度高的一种查找方式,目前在爬虫爬取,对特定的内容的抓包,登录的验证等多个方面都用得上正则表达式,但是由于其实一种灵活的 查找,所以我们要付出的代价就是相应使用的复杂,复杂度表现在语法上的不便记忆和应用层面上的易出错,今天我们就来谈谈正则表达式在应用层面上常出现的错 误
二、正则表达式常见坑与注意点
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中你可能会遇到的一些坑,以及一些问题的实现思路,如果在这里有什么地方说错的,欢迎大家帮忙指正,在此不胜感激,如果你觉得这篇文章对你有帮助的话请为我点一个赞,你的点赞是我前进的动力。后续如果是大家有什么问题的话,也欢迎大家留言共同探讨