1.什么是正则表达式
定义: 一个用来搜索、匹配、处理一些符合特定语法规则的一个强大的字符串处理工具。
用途: 进行特定字符和字符串的搜索
替换字符串中指定的字符或字符串
验证字符串是否符合需求
2.为什么使用正则表达式?
大多数时候做开发其实不用正则表达式也能完成开发,但是学会了正则表达式可以帮助我们更加快速开发。
这是一个栗子:
str = "sad213jkls456poi412poippsd987a1";
将上面的字符串中的数字全部提取出来保存为数组,要求相连的数字保存为一个值
最终答案应该为: [213,456,412,987,1]
我们先不使用正则表达式去提取数据:
let testStr = "sad213jkls456poi412poippsd987a1"; let arr = []; let tempStr =""; for(let i=0; i< testStr.length;i++){ let n = testStr.charAt(i); if(n>=0 && n<=9){ //如果n是数字 tempStr+=n; //验证最后的数字 // if(i == testStr.length-1){ // if(tempStr) arr.push(tempStr); // tempStr = ""; // } }else{ //不是数字将temlStr push到arr中,并清空tempStr重新计算 if(tempStr) arr.push(tempStr); tempStr = ""; } } if(testStr) arr.push(tempStr); //验证最后的数字 console.log(arr)
接下来使用正则表达式验证:
let testStr = "sad213jkls456poi412poippsd987a1"; let arr = testStr.match(/d+/g); console.log(arr)
我那个去,一句话就能提取了,牛x!
3.正则表达式的书写规则
//正则的书写方法 //1.字面量写法 优点:书写方便简介,缺点: 不支持变量 let re = /abc/; //2.构造函数形式 优点:支持变量,缺点: 需要注意字符转义规则 let re2 = new RegExp('abc'); //使用new
4.元字符 -- 有特殊意义的标识
d : 匹配数字
w : 匹配数字、字母、下划线
s :查找空白字符
D : 查找非数字字符。
W : 匹配除了 数字、字母、下划线
S : 查找非空白字符。
: 匹配单词边界。
B : 匹配非单词边界。
//元字符 有特殊含义的标识 let testStr = "sdasda-a123-sifah12300a.sadmn" //假如我们要查找字符串中出现的第一个数字,并且知道该数字为1,可以使用indexOf console.log(testStr.indexOf('1')); //但是如果我们不知道该数字是多少呢? let re = /d/; // d 表示匹配数字 console.log(testStr.match(re)); //返回一个数组,包括第一个数字出现的位置,值,还有操作的字符串
//空白字符 s(包括空格,制表符,特殊空白字符等) let testStr = " 我的左边 有空白,右边还是 有空白 "; let re = /s/g; //匹配所有空白字符 let re2 = /^s+/g; //匹配开头的空白字符 let re3 = /s+$/g; //匹配结尾的空白字符 let re4 = /^s+ | s+$/g; //匹配开头和结尾的空白字符 let re5 = /[^s+]s+[^s+$]/g; //匹配字符串中间空白字符 console.log('('+testStr+')');//( 我的左边 有空白,右边还是 有空白 ) //去除字符串的所有空白字符 console.log('('+testStr.replace(re,"")+')');//(我的左边有空白,右边还是有空白) //去除开头的空白字符 console.log('('+testStr.replace(re2,"")+')');//(我的左边 有空白,右边还是 有空白 ) //去除结尾的空白字符 console.log('('+testStr.replace(re3,"")+')');//(我的左边 有空白,右边还是 有空白 ) //去除字符串开头和结尾字符 console.log('('+testStr.replace(re4,"")+')');//(我的左边 有空白,右边还是 有空白) //去除字符串中间的字符 console.log('('+testStr.replace(re5,"")+')');//( 我的左空白,右边还空白 )
//单词边界 let testStr = "active act sky"; //匹配act let re = /act/; //匹配单独的act 不匹配active let re2 = /act/; console.log(testStr.match(re));//act", index: 0, input: "active act sky"... console.log(testStr.match(re2)); //"act", index: 7, input: "active act sky" .. //匹配左右都不属于单词边界的't' let testStr2 = "act active sky"; let re3 = /BtB/; console.log(testStr2.match(re3)); //"t", index: 6, input: "act active sky"...
5.量词--代表匹配多少个
let re = /d+/gm; //要提取数字的正则表达式 let testStr = "sad213jkls456poi412poippsd987a1"; //d 后面的 '+' 就是一个量词,他代表匹配至少一个 let arr = testStr.match(/d+/g); console.log(arr)
值得注意的是可以使用 {n,m}来表示最少匹配和最多匹配
{n,m}最少匹配n次和最多匹配m次
{n}, 表示匹配n次.
{n,} 只写了n,并且留 了', ',不写m ,则表示至少匹配n次,不限制最多匹配
更多元字符和量词可以参考菜鸟教程 - > 点我查看
6.范围匹配
[asdf] 匹配asdf中任意一个
[0-9] 匹配0-9数字
[a-z] 匹配小写字母a到小写字符z中任意一个字母
[A-Z] 匹配大写字母A到大写字符Z中任意一个字母
[A-z] 匹配任意一个字母,不区分大小写
[u4e00-u9fa5] 匹配中文
let testStr = "abcsadarcadcjlsjja2coqweycyaRc"; //匹配axc 模式的字符串,x为字母 let re = /a[A-z]c/g; console.log(testStr.match(re),"字母")// ["abc", "arc", "adc", "aRc"] "字母" let re2 = /a[0-9]c/g; //匹配axc 模式的字符串,x为数字 console.log(testStr.match(re2),"数字") //["a2c"] "数字"
let testStr = "ad啊萨达sduiow萨达-sd我我 萨达apoi"; let re = /[u4e00-u9fa5]/g; //匹配单个中文 console.log(testStr.match(re)) //["啊", "萨", "达", "萨", "达", "我", "我", "萨", "达"] let re2 = /[u4e00-u9fa5]+/g; //匹配多个中文 console.log(testStr.match(re2)) //["啊萨达", "萨达", "我我", "萨达"]
接下来做一个组合练习
//组合练习 let testStr = "adsas22jl98dkkkja213jklsd9qwe9t9yt9xz98xcz4xzc23"; //提取数字加字母组合的数组,要求字母至少一个,数字只能有一个 let re = /[A-z]+d{1}/g; console.log(testStr.match(re));//["adsas2", "jl9", "dkkkja2", "jklsd9", "qwe9", "t9", "yt9", "xz9", "xcz4", "xzc2"]
{1} 可以省略,因为d默认只会匹配一次
7.分组
使用()对正则表达式进行分组,每一个()为子组
每一个子组都是一个正则表达式
通过分组,可以改变量词的影响范围
/[a-z]d+/ 和 /([a-z]d)+/ 匹配的就不同
let testStr = "a12jsdj2j1s4du2u1y24osf9lo90msad90xc0"; //找到 1个字母加一个数字组合的数组 let re = /([A-z]d)+/g; //量词只能影响前面一个匹配模式或者前面一个分组--'()'的内容 console.log(testStr.match(re),"分组")//["a1", "j2j1s4", "u2u1y2", "f9", "o9", "d9", "c0"] "分组"
8.位置限制
^ : 匹配字符串开始位置的字符
$: 匹配字符串结束位置的字符
//位置限制 let testStr = "123adsad7986adsla290"; let re = /^d+/g; //匹配开始位置的多个数字 console.log(testStr.match(re)); //["123"] let re2 = /d+$/g; //匹配结束位置的多个数字 console.log(testStr.match(re2)); //["290"]
9.修饰符
g: 匹配所有符合规则的字符串
i: 忽略大小写
m: 匹配多行 (需要配合 ^ 或者 $ 使用才容易看出区别)
举个栗子:
以下是html 内容和js内容
<div class="main"> <textarea id="txt"></textarea> <button id="btn">获取</button> </div>
//修饰符 let testStr = "ASDAad213AAW2378SDLXNszx0808Ads08"; let re = /[a-z]+/g; //全局搜索 let re1 = /[a-z]+/gi; //全局搜索 + 忽略大小写 console.log(testStr.match(re)); // ["ad", "szx", "ds"] console.log(testStr.match(re1)); //["ASDAad", "AAW", "SDLXNszx", "Ads"] let oBtn = document.getElementById("btn"); let oTxt = document.getElementById("txt"); let re3 = /^d+/g;//获取数字开头的字符串 let re4 = /^d+/gm;//获取数字开头的字符串, 多行 oBtn.onclick = function(){ let val = oTxt.value; console.log(val.match(re3)) //["1231"] console.log(val.match(re4)) //["1231", "123", "56"] }
下面是textarea填写内容
10.范围排除
[^abc] : 表示除了abc之外的字符
[^0-9] : 表示除了0-9之外的字符
[^a-z] : 表示除了a-z之外的字符
......
在范围匹配里面 用 ^ 开头的表示除了xx以外
[a^bc] : 这里的^不是在开头位置, 只能表示一个普通的字符
//范围排除 let testStr = "abc-adc-aac-aec-akcadl123kas21chcl2a^c"; let re = /a[bcd]c/g; //匹配 ["abc", "adc"] let re2 = /a[^bcd]c/g;//匹配除了abc,acc,adc let re3 = /a[b^cd]c/g;//匹配abc,acc,adc,a^c console.log(testStr.match(re)); //["abc", "adc"] console.log(testStr.match(re2)); // ["aac", "aec", "akc", "a^c"] console.log(testStr.match(re3)); // ["abc", "adc", "a^c"]
11.多选匹配
使用 | 隔开 分别返回 | 两边各自匹配的结果
举个栗子:
将大写字母和小写字符 分别匹配
//多选匹配 let testStr = "sdad23ASDAkjlOU20isdEWYmz082"; let re = /[a-z]+|[A-Z]+/g; console.log(testStr.match(re));// ["sdad", "ASDA", "kjl", "OU", "isd", "EWY", "mz"]
12.正则方法
test() : 用于验证字符串是否符合正则表达式的规则
exec(): 匹配符串正则表达式的 字符串和改字符串出现的位置 (有点类似与macth)
栗子:
test()
<div> <input type="text" id="phone" placeholder="输入手机号"> <button id="verfityPhone">验证手机号</button> </div> <div> <input type="text" id="qq" placeholder="输入qq号"> <button id="verfityQq">验证qq号</button> </div>
//正则表达式方法 test() let testStr = "32ads12398829"; let testStr1 = "213908"; let re = /^d+$/; //验证是否为纯数字 console.log(re.test(testStr)) //false console.log(re.test(testStr1)) //true //验证手机号 以1开头 第二个数字可以为[3,5,7,9] 总共11位 let rePhone = /^1[3579]d{9}$/; let verfityPhone = document.getElementById("verfityPhone"); let phone = document.getElementById("phone"); verfityPhone.onclick = function(){ if(rePhone.test(phone.value)){ alert(phone.value + "是手机号") }else{ alert(phone.value + "不是手机号") } } //验证邮箱 验证qq号码 5-11位 let reQq = /^[1-9]d{4,10}$/; let verfityQq = document.getElementById("verfityQq"); let qq = document.getElementById("qq"); verfityQq.onclick = function(){ if(reQq.test(qq.value)){ alert(qq.value + "是qq号") }else{ alert(qq.value + "不是qq号") } }
exec()
//正则表达式方法: exec() let testStr = "ads213;asdaj230-9ksldakadasd80823hywqey"; let re = /d+/; //不在全局作用下和match 返回值一样 let re1 = /d+/g; console.log(re1.lastIndex); //0 初始值 console.log(re1.exec(testStr)); //['213',...] console.log(re1.lastIndex);//6 console.log(re1.exec(testStr)); //['230',...] console.log(re1.lastIndex);//15 console.log(re1.exec(testStr)); //['9',...] console.log(re1.lastIndex);//17 console.log(re1.exec(testStr)); //['80823'] console.log(re1.lastIndex);//33 console.log(re1.exec(testStr)); //null console.log(re1.lastIndex);//0 找不到后重置为0
lastIndex: 用于标记exec() 下一次执行匹配的开始位置
非全局模式下 exec()和match()返回值是一样的。
全局作用下,exec()一次只能返回一个匹配的值,但是会记录上一次值的lastIndex位置,依次执行就会依次查找,直到最后找不到匹配的字符返回null,然后重置lastIndex 为0, 循环往复。
13.支持正则表达式的字符串方法
search() : 查找指定字符在字符串中出现的位置(只能返回字符第一次出现的位置,若没有找到,返回-1)
match(): 匹配正则表达式的
split(); 按某种格式分割字符串,返回数组
replace(): 替换字符串中符合正则表达式匹配的的值
栗子:
search()
//正则表达式字符串方法 search() let testStr = "asd2131sad"; let re = /d+/g; //只返回第一个匹配到的index,没有找到则返回-1 console.log(testStr.search(re)); //3
replace() 过滤敏感词
//正则表达式字符串方法 replace() let testStr = "我是中华人民共和国公民,我爱我的祖国!"; let re = /中华人民共和国/g; let res = testStr.replace(re,"*******"); console.log(testStr,res);//我是中华人民共和国公民,我爱我的祖国! 我是*******公民,我爱我的祖国!
split()
//正则表达式字符串方法 split() let testStr = "asd-123sad-12ad-lgk-sasd"; let arr = testStr.split("-"); //简单的分割方式 console.log(arr); // ["asd", "123sad", "12ad", "lgk", "sasd"] let testStr2 = "asd-123sad-12ad-lgk-sasd"; let re2 = /[a-z]-/g; //字母- 组合形式的分割 let arr2 = testStr2.split(re2); console.log(arr2); //["as", "123sa", "12a", "lg", "sasd"] let testStr3 = "asd-123sad-12ad-lgk-sasd"; let re3 = /d+/g; //使用数字进行分割 let arr3 = testStr3.split(re3); console.log(arr3); //["asd-", "sad-", "ad-lgk-sasd"]
match() 被吃掉了,不清楚的重新再看此博客..
最后做两个小练习吧!
1.手动封装 getElementByClassName() 方法.
html部分:
<ul id="testUl"> <li class="active">我的className是active</li> <li>2</li> <li>3</li> </ul> <div class="active"> <input type="text" id="phone" placeholder="输入手机号"> <button id="verfityPhone">验证手机号</button> </div>
js部分:
//根据类名查找元素 function getElByClass(cName,container){ //匹配单词边界的 cName let re = new RegExp('\b' +cName+ '\b'); //查找到所有的tagName标签,可以传入指定的容器,然后查找 let allElem = (container || document).getElementsByTagName('*'); //初始化返回数据 let arr = []; for(let i=0 ;i<allElem.length; i++){ //判断dom元素是否满足匹配的正则表达式,是的话就存入数组 if(re.test(allElem[i].className)){ arr.push(allElem[i]); } } return arr; } getElByClass('active'); //[li.active, div.active] getElByClass('active',document.getElementById('testUl')); //[li.active]
2.实现简单的数据绑定模板.
html:
<div> <h2>简易模板渲染引擎</h2> <div id="wrap"></div> </div>
js:
<script> //简易模板引擎实现 let tpl = document.getElementById("tpl"); let wrap = document.getElementById("wrap"); let newsData = [ {title: "华为CFO孟晚舟保释听证后 加拿大人对美国很恼火",content:"当地时间10日,加拿大不列颠哥伦比亚省高等法院继续召开对华为CFO孟晚舟女士的保释听证会。由于当天的庭审没有得出结论,法官表示11日将继续举行听证会。",author:"Samson"}, {title: "孟晚舟一家在温哥华的住宅遭不明人士闯入",content:"白宫经济顾问拉里·库德洛(Larry Kudlow)周日表示,他不能确保总统特朗普不会把释放孟晚舟来作为与中国更广泛的贸易谈判的一部分。"}, {title: "孟晚舟持几国护照?她的哪项人权遭侵犯?外交部回应",content:"问:据报道,欧盟委员会副主席安西普称,欧盟不得不对华为等中国企业感到担忧。中国政府可能要求科技企业与情报部门合作,如通过安装“强制后门”访问加密数据。中方对此有何回应?"}, {title: "胡锡进谈康明凯被拘:没证据说它是中国政府的报复",content:"路透社星期二晚上报道说,加拿大前外交官、国际预防危机组织中国分析师康明凯(Michael Kovrig)已在中国被扣押。路透社的这一报道是根据康明凯所在上述组织的消息发出的,其准确性不得而知,中国和加拿大官方都还没有回应此事。"}, {title: "孟晚舟被扣后遭粗暴对待 媒体:加拿大为虎作伥",content:"加拿大不列颠哥伦比亚省高等法院当地时间星期五举行华为高管孟晚舟保释听证会,在未作出裁决的情况下宣布休庭,星期一继续开庭。"} ] wrap.innerHTML = tpl2Html(tpl.innerHTML,newsData); //模板转HTML function tpl2Html(tempHtml, data){ let sHtml = ''; for(let i=0 ; i<data.length; i++){ sHtml+= replaceTemp(data[i]); } function replaceTemp(d){ let re,t=tempHtml; for(let k in d){ let re = new RegExp('{{(\s)*' + k + '(\s)*}}'); t = t.replace(re, d[k]); } return t; } return sHtml; } </script>
最终效果就是这样的:
拜了个拜。
更新一下进阶教程 :