zoukankan      html  css  js  c++  java
  • 那些年我们一起走过的正则表达式的坑

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

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

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

    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=/([1-4]d{1,2})s?1/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>)[sS]*?(?=</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>[sS]*?(?=</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>[sS]*?(?=</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中你可能会遇到的一些坑,以及一些问题的实现思路,如果在这里有什么地方说错的,欢迎大家帮忙指正,在此不胜感激,如果你觉得这篇文章对你有帮助的话请为我点一个赞,你的点赞是我前进的动力。后续如果是大家有什么问题的话,也欢迎大家留言共同探讨

  • 相关阅读:
    Java反射机制DOME
    Contos7 装bcm4312无线网卡驱动
    windows8.1+centos7双系统(装完centos后无win8引导)
    request+response
    HTTP协议+servlet配置
    类加载和反射
    线程池+线程安全
    IO流之Properties(String键值对)+序列流+打印流+commons-IO(最终流程)
    IO流之字节流 +字符流 (复制文件)
    IO流
  • 原文地址:https://www.cnblogs.com/st-leslie/p/5296976.html
Copyright © 2011-2022 走看看