学习之前先来说一说一些概念
子项
1.正则的一个分组为一个子项,子项的匹配结果可以在这个子项之后被使用
2.子项是有顺序的,以(出现的位置顺序从左到右,第一个'()'--分组 包含的为第一子项,第二个为第二子项,一次类推)
3.可以在子项后面使用\n的形式来反向引用子项的匹配结果.(n为子项的序号,\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
这个方法并非标准方法,而且基于最近一次使用正则表达式来判断的,若多人异步操作,可能导致结果出错,因此不建议投入到正式的使用当中。
子项的反向引用
\n表示第几个子项的引用结果
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+)\w\1/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+)>[\n\t\r\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"]