正则表达式 正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
感受正则的魅力 1 2 3 4 5 6 7 8 9 10 11 12 let title = "现在是2020年11月10日13点15分" ;let time = [...title].filter((item ) => !Number .isNaN(Number .parseInt(item)));console .log(time.join("" ));let numbs = title.match(/\d/g );console .log(numbs.join("" ));console .log(time.join("" ) === numbs.join("" ));
匹配模式
g 全局匹配
i 不区分大小写
m 多行匹配
s 将字符串视为单行匹配
y 模式表示匹配到不符合的就停掉,不会继续往后匹配,必须连续的符合条件的
字面量方式创建正则表达式 1 2 3 4 5 6 7 let title = "songzhengxiang" ;console .log(/s/ .test(title));let reg = /a/ ;console .log(reg.test(title));
选择符使用:或者
1 2 3 4 5 6 let title = "songzhengxiang" ;console .log(/song|x/ .test(title));let tel = "020-9999999" ;console .log(/(010|020)\-\d{7,8}/ .test(tel));
原子表和原子组选择符
1 2 3 4 5 6 7 8 9 10 let reg = /[123]/g ;let reg2 = /(123|456)/g ;let title = "1234688" ;console .log(reg.test(title)); console .log(reg2.test(title)); console .log(title.match(reg)); console .log(title.match(reg2));
正则表达式中的转义符
1 2 3 4 5 6 7 8 9 10 let numb = 23.32 ;let reg = /\d+\.\d+/ ;console .log(reg.test(numb));let url = "https://www.baidu.com" ;let urlReg = /https?:\/\/\w+\.\w+\.\w+/ ;console .log(urlReg.test(url));
字符边界约束
1 2 3 4 5 let numb = "125499999" ;let numreg = /^\d{5,9}$/ ;console .log(numreg.test(numb));
数值与空白元字符
\d,匹配数字
\D,匹配除了数字
[],中括号里面出现的东西就要,如果中括号里面加上^表示不匹配中括号里面的内容
\s,小写的 s 表示匹配空格
\S,大写的 S 表示匹配除了空格
+号匹配多个字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let tel = `李四:010-56948754,张三:020-23522222` ;console .log(tel.match(/\d/ ));console .log(tel.match(/\d+/ ));console .log(tel.match(/\d{3}\-\d{8,9}/g ));console .log(tel.match(/\D+/g ));console .log(tel.match(/[^:,\d\s-]+/g ));
w 和 W 元字符
\w 小写的 w 表示匹配字母、数字、下划线
\W 大写的 w 表示匹配不是字母、数字、下划线
例子:匹配邮箱
1 2 3 4 5 let email = "15039155555@163.com" ;let emailreg = /^\w+@\w+\.\w+$/ ;console .log(email.match(emailreg));console .log(emailreg.test(email));
点元字符使用
1 2 3 4 5 6 7 8 9 10 11 12 13 let title = `15039155555 @163.com ` ;console .log(title.match(/.+/g ));let nwetitle = title .match(/.+/ s)[0 ] .match(/[^\s]*/g ) .join("" ); console .log(nwetitle);
如何精巧匹配所有字符
[\s\S] 匹配空格和不是空格,两个都加上表示所有
[\d\D] 匹配数字和不是数字,两个都加上表示所有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let html = ` <span> songzhnegxiang SONG Xiang </span> ` ;console .log(html.match(/<span>[\s\S]+<\/span>/ ));console .log(html.match(/<span>[\d\D]+<\/span>/ ));
i 和 g 模式修正符
1 2 3 4 5 6 7 8 let name = "SongZhengSiang" ;console .log(name.match(/s/gi ));let time = "2020/11/10" ;console .log(time.replace(/\//g , "-" ));
m 多行匹配修正符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let lessonobj = ` #1 js,200元 # #2 vue,500元 # #3 angular,199元 # song #4 node.js,188元 # ` ;let lesobj = lessonobj.match(/\s*#\d+\s+.+\s+#\s+$/gm ).map((item ) => { item = item.replace(/\s*#\d\s*/ , "" ).replace(/\s*#\s*/ , "" ); let [name, price] = item.split("," ); return { name, price }; }); console .log(lesobj);
汉字和字符属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let name = "songZX,你好中国,upup....加油!!!" ;let str = "豆腐" ;console .log(name.match(/[a-z]+/gi )); console .log(name.match(/\p{P}/gu )); let strs = str.match(/\p{sc=Han}+/gu );console .log(strs); let hanzi = name.match(/[\u4e00-\u9fa5]+/g );console .log(hanzi);
lastIndex 属性的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 let name = "songzx" ;console .log(name.match(/\w/ ));let reg = /\w/g ;while ((res = reg.exec(name))) { console .log(res); console .log(reg.lastIndex); }
有效率的 y 模式 y 模式表示匹配到不符合的就停掉,不会继续往后匹配,必须连续的符合条件的
1 2 3 4 5 6 7 8 9 10 11 12 let name = "我的qq号是,1111111111,22224545488,6411313416544婚姻加入" ;let reg = /(\d+),?/y ;reg.lastIndex = 7 ; let qqList = [];while ((res = reg.exec(name))) { console .log(res); qqList.push(res[1 ]); } console .log(qqList);
原子表的基本使用 1 2 3 4 5 6 7 8 9 let name = "songzhengxiang" ;let namereg = /[szx]/g ;console .log(name.match(namereg));let time = "2020-s11-s13" ;let reg = /^\d{4}([-\/])(s)\d{2}\1\2\d{2}$/ ;console .log(time.match(reg));
区间匹配
[a-z] 匹配 26 位小写字母
[0-9] 匹配 0-9 之间的数字,包含 0 和 9
1 2 3 4 5 6 7 8 9 10 let a = "s5df5sf5s165s6dfsdf513d2f" ;let numreg = /[0-9]+/g ;console .log(a.match(numreg)); let objreg = /[a-z]+/g ;console .log(a.match(objreg));
排除匹配 1 2 3 4 let name = "songkkkzhenglllxiang" ;let reg = /[^kl]+/g ;console .log(name.match(reg));
原子表字符不会解析 1 2 3 4 let name = "(songzheng).+" ;let reg = /[().+]/g ;console .log(name.match(reg));
使用正则去除字符串中的所有空格 1 2 3 4 5 6 let title = " 111 2 33 " ;function trimreg (data ) { return data.match(/[^\s]+/gm ).join("" ); } console .log(trimreg(title));
认识原子组 一个小括号包起来的东西被称为原子组,\1 表示与第一个原子组相同的内容
1 2 3 4 5 6 7 8 let dom = ` <h1>标题一</h1> <h2>标题二</h2> ` ;let reg = /<(h[1-6])>[\s\S]*<\/\1>/g ;console .log(dom.match(reg));
邮箱验证使用原子组
验证邮箱表达式:/^[\da-z][\w.]+@(\w+.)+(com|cn|org)$/i
含义:以数字或者字母开头,数字字母下划线为主体,一个@符号,后面跟上数字字母下划线和小数点,可以为多个,以 com 或 cn 或 org 结尾
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <div > <input type ="text" name ="email" value ="" /> </div > <script > let input = document .querySelector("[name = 'email']" ); /* 邮箱正则 以数字或者字母开头,数字字母下划线为主体,一个@符号 后面跟上数字字母下划线和小数点,可以为多个 以com 或 cn 或 org结尾 */ let emailreg = /^[\da-z][\w.]+@(\w+\.)+(com|cn|org)$/i ; input.addEventListener("keyup" , function ( ) { if (emailreg.test(this .value)) { input.className = "success" ; } else { input.className = "error" ; } }); </script >
嵌套分组和不记录分组 原子组里面加上?:表示不记录该原子组,但是原子组的功能仍然生效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let url = ` http://www.baidu.com https://taobao.cn https://www.zhifubao.com ` ;let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|cn))/gi ;let urls = [];while ((res = reg.exec(url))) { urls.push(res[1 ]); } console .log(urls);
重复匹配的使用
+:一个或者多个
*:零个或者多个
?:有或者没有
{1,2}:一个到两个,最少一个,最多 2 连个,数字随便定义
1 2 3 4 5 6 7 8 9 10 11 12 let name = "sooooo" ;console .log(name.match(/so+/ )); console .log(name.match(/so*/ )); console .log(name.match(/so?/ )); console .log(name.match(/so{1,2}/ ));
重复匹配对原子组影响 1 2 3 let name = "sososososososos" ;console .log(name.match(/(so)+/g ));
禁止贪婪
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let name = "soooooo" ;let reg = /so*?/g ;console .log(name.match(reg)); reg = /so+?/g ; console .log(name.match(reg)); reg = /so??/g ; console .log(name.match(reg)); reg = /so{2,5}?/g ; console .log(name.match(reg));
使用 matchAll 完成全局匹配 matchAll 获取到的是一个迭代对象,可以被遍历到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <main > <h3 > 哈哈哈,sdfsdf</h3 > <h2 > 嘿嘿嘿</h2 > <h4 > 呵呵呵</h4 > <h5 > 嘎嘎嘎</h5 > </main > <script > let main = document .querySelector("main" ); let reg = /<(h[1-6])>([\s\S]+?)<\/\1>/g ; let listall = main.innerHTML.matchAll(reg); let htmldata = []; for (const item of listall) { console .log(item); htmldata.push(item[2]); } console .log(htmldata); </script >
字符串的 search 方法和 match 方法 字符串的 search 方法,找到后返回字符串所在下标,否则返回-1
1 2 3 4 5 6 7 8 9 10 11 12 let urls = ` http://www.baidu.com, http://taobao.com.cn, https://www.tmall.com/ ` ;console .log(urls.search("baidu" )); let reg = /https?:\/\/(\w+)?(\w+\.)+(com|cn)/g ;console .log(urls.match(reg));
$符在正则替换中的使用
$` : 获取替换元素左边的元素
$‘ : 获取替换元素右边的元素
$& : 获取替换元素本身
1 2 3 4 5 6 7 8 9 10 11 12 13 let time = "2020-05-05" ;console .log(time.replace(/-/g , "/" )); let tel = "(0631)-150518888" ;let telreg = /\((\d{3,4})\)-(\d+)/g ;console .log(tel.replace(telreg, "$1/$2" )); let name = "123你好+++" ;console .log(name.replace("你好" , "$`$&$'" ));
原子组起别名
使用 ?<cont>
起原子组的别名
使用 $<cont>
读取别名
1 2 3 4 5 6 7 8 9 10 11 <main > <h2 > 百度</h2 > <h3 > 支付宝</h3 > </main > <script > let main = document .querySelector("main" ); let reg = /<(h[1-6])>(?<cont>.*)?<\/\1>/g ; main.innerHTML = main.innerHTML.replace(reg, `<i > $<cont > </i > `); </script >
后等断言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 张三先生和张三女士是天造地设的一对 <script > let main = document .body; let men = /张三(?=先生)/g ; let wumen = /张三(?=女士)/g ; main.innerHTML = main.innerHTML.replace( men, `<span style ="color:blue" > $&</span > ` ); main.innerHTML = main.innerHTML.replace( wumen, `<span style ="color:pink" > $&</span > ` ); </script >
前等断言
(?<=href=(['"]))
前面是 href=单引号或者双引号的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <main > <a href ="http://baidu.com" > 百度</a > <a href ="http://yahu.com" > 雅虎</a > </main > <script > let main = document .querySelector("main" ); let reg = /(?<=href=(['"])).+(?=\1)/gi ; console .log(main.innerHTML.match(reg)); main.innerHTML = main.innerHTML.replace( reg, "https://songzhengxiang.gitee.io/blog/" ); </script >
后不等断言
1 2 3 4 5 let user = `阅读量:999 新增人数:10人` ;let reg = /\S+(?!\d+)$/g ;console .log(user.match(reg).join("" ));
前不等断言
1 2 3 4 5 let name = "abc123def" ;let reg = /(?<!\d+)[a-z]+/g ;console .log(name.match(reg));
使用断言模糊电话号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let tels = `15036999999` ;let reg = /(\d{3})(\d{4})(\d+)/g ;tels = tels.replace(reg, (v, ...args ) => { args[1 ] = "*" .repeat(4 ); return args.splice(0 , 3 ).join("" ); }); console .log(tels); let newtel = `15036999999` ;let newreg = /(?<=\d{3})\d{4}(?=\d{4})/g ;newtel = newtel.replace(newreg, (v ) => { return "*" .repeat(4 ); }); console .log(newtel);