• javascript 正则表达式 进阶教程


    学习之前先来说一说一些概念

    子项

      1.正则的一个分组为一个子项,子项的匹配结果可以在这个子项之后被使用

      2.子项是有顺序的,以(出现的位置顺序从左到右,第一个'()'--分组 包含的为第一子项,第二个为第二子项,一次类推)

      3.可以在子项后面使用 的形式来反向引用子项的匹配结果.(n为子项的序号, 表示的是子项匹配到的结果,而不是子项规则本身)

    replace方法:

    //replace 参数用法
    
    //1. 第一个参数为字符串
    let testStr = "abc123";
    console.log(testStr.replace("abc","456")); //456123
    //2. 第一个参数为正则表达式
    console.log(testStr.replace(/[a-z]+/,456));//456123
    //3. 第二个参数为function,必须要有返回值,否则默认返回 'undefined'
    console.log(testStr.replace(/[a-z]+/,function(){
        return ;
    })) //undefined123
    console.log(testStr.replace(/[a-z]+/,function(){
        return 456;
    })) //456123
    //第二个参数为字符串时,还可以插入以下的特殊变量来引用子项或与子项相关的内容
    let testStr = "abc123def";
    //1. $$ 表示 '$'
    console.log(testStr.replace(/d+/g,"$$")); //abc$def
    //2. $& 表示 插入的匹配字串
    console.log(testStr.replace(/d+/g,"$&")); //abc123def   
    console.log(testStr.replace(/d+/g,"-$&")); //abc-123def    
    //3. $`表示 插入的匹配字串之前的字符
    console.log(testStr.replace(/d+/g,"$`")); //abcabcdef   
    //4. $'  表示 插入的匹配字串之后的字符
    console.log(testStr.replace(/d+/g,"$'")); //abcdefdef  
    console.log(testStr.replace(/d+/g,"-$'-")); //abc-def-def
    //5. $n  表示 插入的匹配到子项的下标 
    let re = /((d)+)/; //最外层的((d)+)子项为第一子项, (d)为第二子项
    console.log(testStr.replace(re,"$1")); //abc123def  第一个子项匹配到的结果为123
    console.log(testStr.replace(re,"$2")); //abc3def 第二个子项匹配到的结果为3. (子项匹配到多个值的话会返回最后一个值,因此匹配到了123,返回3)
    //replace 第二个参数为 function时,function里面的参数是什么?
    
    let email = "983521365@qq.com";
    
    let re = /w+@w+.[a-z]{2,4}/; //没有子项的正则 
    let newStr = email.replace(re,function(res,index,origin){    
            //如果正则表达式没有子项,则function会返回三个参数,第一个参数为匹配正则的结果,第二个是这个结果开始位置的下标,第三个是被处理的字符串
            console.log(res); //983521365@qq.com
        console.log(index); //0
        console.log(origin); //983521365@qq.com
        return "123";
    })
    console.log(newStr); //123
    
    let re2 = /(w+)@(w+).([a-z]{2,4})/; //有子项的正则 
    let newStr2 = email.replace(re2,function(res,child1,child2,child3,index,origin){    
        //function会返回多个参数,第一个参数为匹配正则的结果,到处第二个是子项最后匹配到的下标位置,最后一个是被处理的字符串,中间的参数则是依次匹配到子项值
        console.log(res); //983521365@qq.com
        console.log(child1); //983521365
        console.log(child2); //qq
        console.log(child3); //com
        console.log(index); //0
        console.log(origin); //983521365@qq.com
        return "123";
    })
    console.log(newStr2); //123            

     使用子项参数修改正则返回值

    //将邮箱的用户名全部替换为大写字母
    let email = "Samson@qq.com";
    let re2 = /(w+)@(w+).([a-z]{2,4})/; //有子项的正则 
    let newStr = email.replace(re2,function(res,child1,child2,child3,index,origin){
        return child1.toUpperCase() + "@" + child2 + "."+child3;
    })
    console.log(newStr); //SAMSON@qq.com
    let sCss = "-webkit-border-radus";
    let re = /-(w)/g; 
    let newCss = sCss.replace(re,function(a,b,c,d){
        return b.toUpperCase();
    })
    console.log(newCss); //WebkitBorderRadus
    let sCss = "-webkit-border-radus";
    let re = /-(w)/g; 
    let newCss = sCss.replace(re,function(res,child,index,origin){
        //第一个匹配到的index 坐标为0 
        return index? child.toUpperCase() : child
    })
    console.log(newCss); //webkitBorderRadus

    小练习1: 给商品价格加上单位和币种

    //小练习1 -- 给商品价格加上单位和币种
    let str = "商品的价格是: 200"; //200
    let re  = /d+/;
    let price = str.replace(re,"¥$&元");
    console.log(price); //商品的价格是: ¥200元

    小练习2:格式化日期

    //使用子项进行日期格式化
    let date = "2018-12-17";
    //将date 替换成 12-17 2018
    let re = /(d{4})-(d{1,2})-(d{1,2})/g;
    console.log(date.replace(re,'$2-$3 $1')); //12-17 2018

    小练习3:给搜索出的关键字加上高亮效果

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>关键字高亮效果</title>
    </head>
    <body>
        <input type="text" id="txt">
        <button id="btn">搜索</button>
    
        <div id="content">
            乌克兰武装部队总参谋长维克多·穆真科(Viktor Muzhenko)称,“自2014年克里米亚事件以来,俄罗斯构成了‘军事威胁’。”他还称,卫星图像显示,在仅仅两周的时间内,至少有250辆俄罗斯坦克在边境附近集结。
    
    维克多·穆真科甚至称,“很难预测俄罗斯会何时对乌克兰采取战斗行动”。
    
    穆真科说,这些俄罗斯坦克是在刻赤海峡冲突事件后集结起来的,在这起冲突中,20名乌克兰海军军官被扣押,至今还未被释放。
    
    此外,报道还提到,在刻赤海峡事件之后,乌克兰也希望其在亚速海附近军事基地的建设完工。
        </div>
    
    
    
        <script>
            let oTxt = document.getElementById("txt");    
            let oBtn = document.getElementById("btn");    
            let content = document.getElementById("content");
            let originContent = content.innerHTML;
            oBtn.onclick = function(){
                let value = oTxt.value.trim(); //获取输入的值,去掉左右空格
                let re = new RegExp(value,'ig');
                let sHtml = originContent.replace(re,"<span style='background: orange;'>$&</span>"); //在匹配的字符串前后加上带有背景颜色的span标签
                content.innerHTML = sHtml;
            }
        </script>
    </body>
    </html>

    效果图如下:

    用正则表达式替换真的很方便呢.

    RegExp.$n  

    n的值为1-9 ,还可以是下划线

    $n 表示的是第几个子项,而子项是基于最近一次使用的正则表达式。

    $_ 表示最近一次使用正则表达式 测试的字符串

    如果没有子项则返回空字符串。

    let str = "983521365@qq.com"
    let re = /w+@w+.[a-z]{2,4}/;
    re.test(str); //使用正则表达式
    console.log(RegExp.$1);// ""
    console.log(RegExp.$_);// 983521365@qq.com
    //为什么使用正则表达式还是空呢? 原来表达式里面根本没有子项
    
    //重新定义有正则的子项
    re = /(w+)@(w+).([a-z]{2,4})/;
    console.log(RegExp.$1);// ""
    console.log(RegExp.$_);// 983521365@qq.com
    //为什么重新定义了还是空的? 原来是还没有重新使用正则,所以正则匹配的还是之前的表达式
    re.test(str);
    console.log(RegExp.$1);// 983521365
    console.log(RegExp.$2);// 11
    console.log(RegExp.$3);// com
    console.log(RegExp.$_);// 983521365@qq.com

    这个方法并非标准方法,而且基于最近一次使用正则表达式来判断的,若多人异步操作,可能导致结果出错,因此不建议投入到正式的使用当中。

    子项的反向引用

      表示第几个子项的引用结果

    let str = "213as426555aoqwu753333nmab8882138888pqwe9999820222";
    //匹配出所有重复的数字
    let re = /(d)1+/g;
    console.log( str.match(re));// ["555", "3333", "888", "8888", "9999", "222"]
    let str = "ads2a333o333ouoadsba666a666aoiwqeu999w9999owqe";
    let re =  /((d)2+)w1/g;
    console.log(str.match(re));//["333o333", "666a666", "999w999"]

    小练习: 去掉html空白标签

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div id="content">
            <h2 class="title">跨越30年的两封信</h2>
            <h3 >     </h3>
            <h4>
                
            </h4>
            <div>
                <div class="content">

                昨天,有韩国媒体爆料了一起中国粉丝追星的“骚操作”:

                据称,有4名中国粉丝为了追星,先是买了跟偶像同一班的头等舱机票,在成功见到偶像后突然要求下飞机并全额退款。并且,他们还成功了……

                但这却导致机上360名乘客被迫重新安检,航班严重延误。

    </div>
            </div>
            <p></p>
            <p>这是一段测试内容</p>
            <span></span>
        </div>
        
        <script>
            let sHtml = document.getElementById("content").innerHTML;
            let re = /<(w+)></1>/g;
            console.log(sHtml.match(re)); // ["<p></p>", "<span></span>"]
            //改进之后,让他能够匹配到空白字符
            let re2 =  /<(w+)>[
    	
    s]*</1>/g;
            console.log(sHtml.match(re2)); //["<h3> </h3>", "<h4>↵            ↵        </h4>", "<p></p>", "<span></span>"]
        </script>
    </body>
    </html>

    零宽断言

      匹配结果不占长度,断言的判断内容不会被输出

      正先行断言 aaa(?=xxx) aaa紧接该位置之后必须存在xxx才会匹配
      负先行断言 aaa(?!xxx) aaa紧接该位置之后不存在xxx才会匹配
      正后行断言 (?<=xxx)aaa aaa紧接该位置之前必须存在xxx才会匹配
      负后行断言 (?<!xxx)aaa aaa紧接该位置之前不存在xxx才会匹配

     

    let str = "word2013,excel2013,qq2018,yy2016";
    //找到带2013把版本的软件,但是只显示文件名,不显示文件版本
    let re = /w+(2013)/g;
    console.log(str.match(re));//["word2013", "excel2013"] 不满足需求
    //使用正先行断言
    let re2 = /w+(?=2013)/g; //右边必须有2013,但是2013不会被输出
    console.log(str.match(re2)); // ["word", "excel"]
    
    //找到版本号不属于2016的软件
    let re3 = /[a-z]+(?!2016)/g;
    // console.log(str.match(re3));// 负先行断言 ["word", "excel", "qq", "y"] //不满足
    
    let re4 = /[a-z]+(?=d+[^2016])/g; //正先行断言 +范围排除
    console.log(str.match(re4)); //["word", "excel", "qq"]
    
    //匹配出yy的版本号
    let re5 = /[a-z]{2}(?<=[yy])d+/g;
    console.log(str.match(re5)); //["2016"]
    
    //匹配除了yy之外的其他软件版本号
    let re6 = /(?<![yy])d{4}/g;
    console.log(str.match(re6)); //["2013", "2013", "2018"]
  • 相关阅读:
    Typora标题自动编号+设定快捷键技巧
    配置redis 4.0.11 集群
    学会使用 Mysql show processlist 排查问题
    Golang学习的方法和建议
    日志文件删除shell脚本
    运维趋势2019年总结,运维就是要做到"技多不压身"
    我的xshell配色方案,绿色/护眼/留存/备份
    对于api接口的爬虫,通常的解决方法
    maven 打包和构建的Linux命令(mvn)
    Istio的流量管理入门-charlieroro编写
  • 原文地址:https://www.cnblogs.com/zzd0916/p/10130001.html
Copyright © 2020-2023  润新知