后盾人的文档
JS中的正则表达式 基础知识 正则表达式是用于匹配字符串中字符组合的模式,在 JavaScript中,正则表达式也是对象。
对比分析 与普通函数操作字符串来比较,正则表达式可以写出更简洁、功能强大的代码。
下面使用获取字符串中的所有数字来比较函数与正则的差异。
1 2 3 4 5 6 7 let hd = 'zhangjjiiallllliiiiinnnnn132' ; let nums = [...hd].filter(a => !Number .isNaN(parseInt (a))); console .log(nums); console .log(nums.join('' ));
1 2 console .log(hd.match(/\d/g ).join('' ));
创建正则 JS提供字面量与对象两种方式创建正则表达式
字面量创建 使用//
包裹的字面量创建方式是推荐的作法,但它不能在其中使用变量
1 2 let mk = "miketaylor.comuuuuuu" ;console .log(/u/ .test(mk));
下面尝试使用 a
变量时将不可以查询
1 2 3 4 5 6 7 8 9 10 11 <script > let mk = "miketaylorjuly123.cn" ; let site= "t" ; let a = "t" ; console .log(/t/ .test(mk)); console .log(/site/ .test(mk)); console .log(/a/ .test(mk)); console .log(eval (`/${a} /` ).test(mk)); </script >
对象创建 当正则需要动态创建时使用对象方式。
1 2 3 4 5 6 7 8 let mk = 'miketaylorjuly123.cn' ;let test1 = 'u' ;let reg1 = new RegExp ('u' ,'g' );let reg2 = new RegExp (test1 ,'g' );console .log(reg1.test(mk));console .log(reg2.test(mk));
字符串替换:
1 2 3 4 5 6 7 8 9 <script > console .log("abcd" .replace('ab' ,'@@' )); console .log("_a_b_c_d_" .replace(/\w/g ,'@@' )); console .log("_a_b_c_d_" .replace(/\w/g ,search => { return '@@' ; }));</script >
根据用户输入高亮显示内容,支持用户输入正则表达式:
1 2 3 4 5 6 7 8 9 10 <script > const mk = prompt('请输入要检测的内容,支持则正则' ); const reg = new RegExp (mk, "g" ); let body = document .querySelector('#content' ) .innerHTML.replace(reg, search => { return `<span style="color:#ff0000">${search} </span>` ; }); document .body.innerHTML = body; </script >
通过对象创建正则提取标签
1 2 3 4 5 6 7 8 9 10 11 12 13 <body > <h1 > miketaylor.com</h1 > <h1 > miketaylorjuly123.cn</h1 > </body > <script > function element (tag ) { const html = document .body.innerHTML; let reg = new RegExp ("<(" + tag + ")>.+</\\1>" , "g" ); return html.match(reg); }console .table(element("h1" ));</script >
|
这个符号带表选择修释符,也就是 |
左右两侧有一个匹配到就可以。
检测电话是否是上海或北京的坐机
1 2 3 4 5 6 let tel = "010-12345678" ;console .log(tel.match(/010|020\-\d{7,8}/ )); console .log(tel.match(/(010|020)\-\d{7,8}/ ));
匹配字符是否包含miketaylor.cn
或 miketayulorjuly123.cn
字符转义 转义用于改变字符的含义,用来对某个字符有多种语义时的处理。
假如有这样的场景,如果我们想通过正则查找/
符号,但是 /
在正则中有特殊的意义。如果写成///
这会造成解析错误,所以要使用转义语法 /\//
来匹配。
字符边界 使用字符边界符用于控制匹配内容的开始与结束约定。
^
匹配字符串的开始
$
匹配字符串的结束,忽略换行符
检测用户名长度为3~6位,且只能为字母。如果不使用 ^与$
限制将得不到正确结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <body > <input type ="text" name ="user" /> <span > </span > </body > <script > let mk = 'miketaylorjuly123.cn' ; console .log(/\d/ .test(mk)); console .log(/^\d/ .test(mk)); console .log(/\d$/ .test(mk)); console .log(/\d$/ .test(mk)); document .querySelector("[name = 'user']" ).addEventListener("keyup" ,function ( ) { let flag = this .value.match(/^[a-z]{3,6}$/ ) document .querySelector("span" ).innerHTML = flag?"正确" :"错误" ; });</script >
元字符 元字符是正则表达式中的最小元素,只代表单一(一个)字符
字符列表
元字符
说明
示例
\d
匹配任意一个数字
[0-9]
\D
与除了数字以外的任何一个字符 匹配
[^0-9]
\w
与任意一个英文字母,数字或下划线 匹配
[a-zA-Z_]
\W
除了字母,数字或下划线外 与任何字符匹配
[^a-zA-Z_]
\s
任意一个空白字符 匹配,如空格,制表符\t
,换行符\n
[\n\f\r\t\v]
\S
除了空白符外任意一个字符匹配
[^\n\f\r\t\v]
.
匹配除换行符外的任意字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <script > mk = "miketaylor 2021" ; console .log(mk.match(/\d+/g )); let info = `张三:010-20012932233,李四:020-2020321355` ; console .log(info.match(/\d{3}-\d+/g )); console .log(info.match(/[-\d:,]/g )); console .log(info.match(/[-\d:,]+/g )); console .log(info.match(/[^-\d:,]/g )); console .log(info.match(/[^-\d:,]+/g )); let mk2 = "miketaylor 2021" ; console .log(mk2.match(/\D+/g )); console .log(/\s/ .test(mk2)); console .log(mk2.match(/\S+/g )); </script >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <script> let mk = "miketaylorjuly123.cn" ; console .log(mk.match(/\w+/g )); let email = "3105085561@qq.com" ; console .log(email.match(/^\w+@\w+\.\w+$/g )); console .log('jiajialingongzhang@gmail.com' .match(/\W/g )); let username = prompt("Enter your username" ); console .log(/^[a-z]\w{4,9}$/ .test(username)); </script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <script > let mk = "miketaylorjuly123.cn-+!@#$@$#%%^%$&^" ; console .log(mk.match(/.+/g )); let my_site = "https://miketaylorjuly123.cn" ; console .log(my_site.match(/https?:\/\/\w+\.\w+/g )); let my_site2 = ` https: https: `; console .log(my_site2.match(/.+/ s)[0 ]); let tel = '155 8322 3946' ; console .log(tel.match(/\d+ \d+ \d+/ )); </script >
匹配任何字符
1 2 3 4 5 <script > let mk = "mik1123%$#@!#%%^&%^&*()|<>,./;'[]|*/~`etaylorjuly123.cn" ; console .log(/[\s\S]+/ .test(mk)); </script >
模式修饰 正则表达式在执行时会按他们的默认执行方式进行,但有时候默认的处理方式总不能满足我们的需求,所以可以使用模式修正符更改默认方式。
修饰符
说明
i
不区分大小写字母的匹配
g
全局搜索所有匹配内容
m
视为多行
s
视为单行忽略换行符,使用.
可以匹配所有字符
y
从 regexp.lastIndex
开始匹配
u
正确处理四个字符的 UTF-16 编码
模式g与模式i
1 2 3 4 5 6 7 8 9 10 11 12 13 <script > let mk = "miketaylorjuly123.cnV" ; console .log(mk.match(/v/ )); console .log(mk.match(/v/i )); let mk2 = "miketVaVyVloVrjVuly1V23.VcVn" ; console .log(mk2.match(/v/gi )); console .log(mk2.replace(/v/gi , '@' )); </script >
m多行匹配修正符实例
将以 #数字
开始的课程解析为对象结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script > let mk = ` #1 Data Structure,90 # #2 Computer Network,90 # #3 Operation system,85 # 张云 #4 Artificial Vision,100 # `; let lessons = mk.match(/\s*#\d\s+.+#$/gm ).map(v => { v = v.replace(/\s*#\d+\s+/ ,'' ).replace(/\s#/ ,'' ); [name,price] = v.split(',' ); return {name ,price}; }) console .log(JSON .stringify(lessons,null ,2 )); </script >
汉字与字符属性
每个字符都有属性,如L
属性表示是字母,P
表示标点符号,需要结合 u
模式才有效。其他属性简写可以访问 属性的别名 (opens new window) 网站查看。
1 2 3 let mk = "miketaylorjuly123.加加林,冲冲冲。" ; console .log(mk.match(/\p{L}/gu )); console .log(mk.match(/\p{P}/gu ));
字符也有Unicode文字系统属性 Script=文字系统
,下面是使用 \p{sc=Han}
获取中文字符 han
为中文系统,其他语言请查看 文字语言表
1 2 3 4 let hd = ` 张三:010-99999999,李四:020-88888888` ;let res = hd.match(/\p{sc=Han}+/gu );console .log(res);
使用 u
模式可以正确处理四个字符的 UTF-16 字节编码
1 2 3 4 let str = "𝒳𝒴" ;console .table(str.match(/[𝒳𝒴]/ )); console .table(str.match(/[𝒳𝒴]/u ));
lastIndex RegExp对象lastIndex
属性可以返回或者设置正则表达式开始匹配的位置
必须结合 g
修饰符使用
对 exec
方法有效
匹配完成时,lastIndex
会被重置为0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <script > let mk = 'miketaylorjuly123.cn' ; let reg = /\w/g ; console .log(mk.match(reg)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); while ((res = reg.exec(mk))){ console .log(res); }</script >
y 我们来对比使用 y
与g
模式,使用 g
模式会一直匹配字符串。
提高检索大文档的效率。
1 2 3 4 5 6 7 8 9 10 11 12 13 <script > let mk = 'lovemikelovetaylor' ; let reg = /l/g ; console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); </script >
1 2 3 4 5 6 7 8 9 10 11 12 13 <script > let mk = 'lovemikelovetaylor' ; let reg = /l/y ; console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); console .log(reg.exec(mk)); console .log(reg.lastIndex); </script >
因为使用 y
模式可以在匹配不到时停止匹配,在匹配下面字符中的qq时可以提高匹配效率。
1 2 3 4 5 6 7 let hd = `铁憨憨QQ号:11111111,999999999,88888888,我将不断学习,并且称为全栈!` ;let reg = /(\d+),?/y ;let qq = []; reg.lastIndex = 7 ;while ((res = reg.exec(hd))) qq.push(res[1 ]);console .log(qq);
原子表 在一组字符中匹配某个元字符,在正则表达式中通过元字符表来完成,就是放到[]
(方括号)中。
使用语法
原子表
说明
[]
只匹配其中的一个原子
[^]
只匹配”除了”其中字符的任意一个原子
[0-9]
匹配0-9任何一个数字
[a-z]
匹配小写a-z任何一个字母
[A-Z]
匹配大写A-Z任何一个字母
实例操作 使用[]
匹配其中任意字符即成功,下例中匹配ue
任何一个字符,而不会当成一个整体来对待。
1 2 3 4 5 <script > let mk = "miketaylorjuly123.cn" ; console .log(/kt/ .test(mk)); console .log(/[kt]/ .test(mk)); </script >
日期匹配
1 2 3 4 5 <script > let date = "2022/02/23" ; console .log(date.match(/^\d{4}([-\/])\d{2}\1\d{2}$/ )); </script >
区间匹配
0-3匹配
1 2 const num = "2" ;console .log(/[0-3]/ .test(num));
匹配a~f间的任意字符
1 2 const hd = "e" ;console .log(/[a-f]/ .test(hd));
顺序为升序否则将报错
1 2 const num = "2" ;console .log(/[3-0]/ .test(num));
字母也要升序否则也报错
1 2 const hd = "houdunren.com" ;console .log(/[f-a]/ .test(hd));
1 2 const hd = "houdunren.com" ;console .log(/[f-a]/ .test(hd));
验证用户名,要求数字开头,后面数字下划线字母,4-7位
1 2 3 4 5 6 7 8 9 <body > <input type ="text" name ="username" > </body > <script > let input = document .querySelector(`[name="username"]` ); input.addEventListener('keyup' ,function ( ) { console .log(this .value.match(/^[a-z]\w+{3,6}$/i )); });</script >
排除匹配
1 2 3 4 let hd = ` 张三:010-99999999,李四:020-88888888` ;let res = hd.match(/[^:\d-,]+/g ); console .log(res);
原子表中有些正则字符不需要转义,如果转义也是没问题的,可以理解为在原子表中.
就是小数点。
1 2 3 4 5 6 7 <script > let str = "(miketaylorjuly123.cn)+" ; console .table(str.match(/[().+]/g )); console .table(str.match(/[\(\)\.\+]/g )); </script >
下面是使用原子表知识删除所有标题
1 2 3 4 5 6 7 8 9 10 11 <body > <p > 憨憨</p > <h1 > miketaylorjuly123.cn</h1 > <h2 > baidu.fanyi.com</h2 > </body > <script > const body = document .body; const reg = /<(h[1-6])>[\s\S]*<\/\1>*/gi ; let content = body.innerHTML.replace(reg, "" ); document .body.innerHTML = content; </script >
匹配所有内容
1 2 3 4 5 6 7 8 <script > let mk = ` miketaylor Juile `; console .log(mk.match(/.+/g s)); console .log(mk.match(/[\S\s]+/g s)); </script >
原子组
如果一次要匹配多个元子,可以通过元子组完成
原子组与原子表的差别在于原子组一次匹配多个元子,而原子表则是匹配任意一个字符
元字符组用 ()
包裹
下面使用原子组匹配 h
标签。
1 2 3 4 5 6 7 8 9 <script > let mk = ` <h1 > miketaylorjuly</h1 > <h2 > Linux</h2 > `; let reg = /<(h[1-6])>[\s\S]*<\/\1>/i ; console .log(mk.match(reg)); </script >
基本使用 没有添加 g
模式修正符时只匹配到第一个,匹配到的信息包含以下数据
变量
说明
0
匹配到的完整内容
1,2….
匹配到的原子组
index
原字符串中的位置
input
原字符串
groups
命名分组
在match
中使用原子组匹配,会将每个组数据返回到结果中
0 为匹配到的完成内容
1/2 等 为原子级内容
index 匹配的开始位置
input 原始数据
groups 组别名
邮箱匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <body > <input type ="text" name ="mail" value ="23134565556@qq.com" > <input type ="text" name ="website" value ="miketaylorjuly123@qq.com.cn" > </body > <script > let mail = document .querySelector(`[name = "mail"]` ).value; let website = document .querySelector(`[name = "website"]` ).value; let reg = /^[\w-]+@[\w-]+\.(com|org|cc|cn|net)$/i ; console .log(mail.match(reg)); let reg_pro = /^[\w-]+@([\w-]+\.)+(com|org|cc|cn|net)$/i ; console .log(website.match(reg_pro)); </script >
邮箱匹配并输出结果
1 2 3 4 5 6 7 8 9 10 11 12 <body > <input type ="text" name ="website" value ="miketaylorjuly123@qq.com.cn" > <span > </span > </body > <script > let website = document .querySelector(`[name = "website"]` ).addEventListener("keyup" ,function ( ) { let reg_pro = /^[\w-]+@([\w-]+\.)+(com|org|cc|cn|net)$/i ; document .querySelector("span" ).innerHTML = reg_pro.test(this .value)?"正确" :"错误" ; });</script >
引用分组 \n
在匹配时引用原子组, $n
指在替换时使用匹配的组数据。下面将标签替换为p
标签。
1 2 3 4 5 6 7 8 9 <script > let mk = ` <h1 > miketaylorjuly</h1 > <span > </span > <h2 > hulu</h2 > `; let reg = /<(h[1-6])>([\s\S]+)<\/\1>/gi ; console .log(mk.replace(reg, '<p>$2</p>' )); </script >
替换进阶
1 2 3 4 5 6 7 8 9 10 11 12 13 <script > let mk = ` <h1 > miketaylorjuly</h1 > <span > </span > <h2 > hulu</h2 > `; let reg = /<(h[1-6])>(\w([\s\S]+))<\/\1>/gi ; // console.log(mk.replace(reg, '<p > $2</p > ')); let res = mk.replace(reg, (p0,p1,p2,p3 )=> { return `<span>${p2} </span>` ; }); console .log(res); </script >
嵌套分组与不记录组 如果只希望组参与匹配,便不希望返回到结果中使用 (?:
处理。下面是获取所有域名的示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <script > let mk = ` https: https: https: `; let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|org|cn|cc))/ig ; console .dir(reg.exec(mk)); console .log(reg.lastIndex); console .dir(reg.exec(mk)); console .log(reg.lastIndex); console .dir(reg.exec(mk)); console .log(reg.lastIndex); console .dir(reg.exec(mk)); console .log(reg.lastIndex); let urls = []; while ((res = reg.exec(mk))){ urls.push(res[1]); } console .table(urls); </script >
分组别名 如果希望返回的组数据更清晰,可以为原子组编号,结果将保存在返回的 groups
字段中
1 2 let hd = "<h1>miketaylorjuly123.cn</h1>" ;console .dir(hd.match(/<(?<tag>h[1-6])[\s\S]*<\/\1>/ ));
组别名使用 ?<>
形式定义,下面将标签替换为p
标签
1 2 3 4 5 6 7 let hd = ` <h1>miketaylor</h1> <span>铁憨憨</span> <h2>macos</h2> ` ;let reg = /<(?<tag>h[1-6])>(?<con>[\s\S]*)<\/\1>/gi ;console .log(hd.replace(reg, `<p>$<con></p>` ));
重复匹配 如果要重复匹配一些内容时我们要使用重复匹配修饰符,包括以下几种。
符号
说明
*
重复零次或更多次
+
重复一次或更多次
?
重复零次或一次
{n}
重复n次
{n,}
重复n次或更多次
{n,m}
重复n到m次
因为正则最小单位是元字符,而我们很少只匹配一个元字符如a、b所以基本上重复匹配在每条正则语句中都是必用到的内容。
多重重复匹配
1 2 3 4 5 6 7 8 9 <script > let mk= 'mkkkkkkkkkk' ; console .log(mk.match(/mk+/ )); console .log(mk.match(/mk*/ )); console .log(mk.match(/mk{2,5}/ )); console .log(mk.match(/mk{1,}/ )); console .log(mk.match(/mk{0,}/ )); console .log(mk.match(/mk?/ )); </script >
电话匹配正则
1 2 3 4 5 6 <script > let mk = 'mkkkkkkkkmkmkmk' ; console .log(mk.match(/(mk)+/g )); let tel = '0315-3693243' ; console .log(tel.match(/^0\d{2,3}\-\d{7,8}$/ )); </script >
网站用户名验证
1 2 3 4 5 6 7 8 9 10 11 <body > <input type ="text " name ="username" > </body > <script > document .querySelector(`[name = "username"]` ).addEventListener('keyup' ,(e )=> { const value =e.target.value; console .log(value); let reg = /^[a-z][\w-]{2,7}$/i ; console .log(reg.test(value)); }); </script >
批量使用正则完成密码验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script > const input = document .querySelector(`[name="password"]` ); input.addEventListener('keyup' ,e => { const value = e.target.value; const regs = [ /^[a-z0-9]{5,10}$/i, /[A-Z]/, /[0-9]/, ] let state = regs.every(e => e.test(value)); console .log(state?"正确" :"错误" ); });</script >
禁止贪婪 正则表达式在进行重复匹配时,默认是贪婪匹配模式,也就是说会尽量匹配更多内容,但是有的时候我们并不希望他匹配更多内容,这时可以通过?进行修饰来禁止重复匹配。
使用
说明
*?
重复任意次,但尽可能少重复
+?
重复1次或更多次,但尽可能少重复
??
重复0次或1次,但尽可能少重复
{n,m}?
重复n到m次,但尽可能少重复
{n,}?
重复n次以上,但尽可能少重复
1 2 3 4 5 6 7 8 9 <script > let mk = 'mkkkkkkk' ; console .log(mk.match(/mk+?/ )); console .log(mk.match(/mk*?/ )); console .log(mk.match(/mk{2,100}/ )); console .log(mk.match(/mk{2,100}?/ )); console .log(mk.match(/mk{2,}?/ )); console .log(mk.match(/mk??/ )); </script >
将所有span更换为h4
并描色,并在内容前加上 铁憨憨-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > </head > <body > <main > <span > wangbuer</span > <span > baidu.com</span > <span > miketaylorjuly123.cn</span > </main > </body > <script > const main = document .querySelector("main" ); const reg = /<span>([\s\S]+?)<\/span>/gi ; main.innerHTML = main.innerHTML.replace(reg,(v , p1 )=> { console .log(p1); return `<h4 style="color:#8080ff">铁憨憨--${p1} </h4>` ; });</script > </html >
下面是使用禁止贪婪查找页面中的标题元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <body> <h1> houdunren.com </h1> <h2>miketaylorjuly123.cn</h2> <h3></H3> <H1></H1> </body> <script> let body = document .body.innerHTML; let reg = /<(h[1-6])>[\s\S]*?<\/\1>/gi ; console .table(body.match(reg)); </script>
全局匹配 问题分析 使用match
全局获取页面中标签内容,但并不会返回匹配细节。
matchAll 在新浏览器中支持使用 matchAll
操作,并返回迭代对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <body > <h1 > wangbuer</h1 > <h2 > baidu.com</h2 > <h1 > 铁憨憨</h1 > </body > <script > let reg = /<(h[1-6])>([\s\S]+?)<\/\1>/ig ; const body = document .body; console .log(body.innerHTML.match(reg)); const mk = body.innerHTML.matchAll(reg); let content = []; console .log(mk); for (const iterator of mk){ console .dir(iterator); content.push(iterator[2]); } console .table(content); </script >
为低版本浏览器定义原型方法matchAll()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <body > <h1 > wangbuer</h1 > <h2 > baidu.com</h2 > <h1 > 铁憨憨</h1 > </body > <script > String .prototype.matchAll=function (reg ) { let res = this .match(reg); if(res){ let str = this .replace(res[0 ],"^" .repeat(res[0 ].length)); let match = str.matchAll(reg) || []; return [res,...match]; } }; let body = document .querySelector(`body` ).innerHTML; let search = body.matchAll(/<(h[1-6])>([\s\S]+?)<\/\1>/ ); console .log(search) </script >
exec 使用 g
模式修正符并结合 exec
循环操作可以获取结果和匹配细节
一定要用模式g!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <body > <h1 > wangbuer</h1 > <h2 > baidu.com</h2 > <h1 > 铁憨憨</h1 > </body > <script > function search (string, reg ) { const matchs = []; while ((data = reg.exec( string))) { matchs.push(data); } return matchs; } console .log(search(document .body.innerHTML, /<(h[1-6])>[\s\S]+?<\/\1>/gi )); </script >
字符方法 下面介绍的方法是 String
提供的支持正则表达式的方法
search search() 方法用于检索字符串中指定的子字符串,也可以使用正则表达式搜索,返回值为索引位置
match 直接使用字符串搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script > let mk = "miketaylorjuly123.cn" ; console .log(mk.search(".cn" )); console .log(mk.search(".@" )); let mk2 = ` https: https: https: `; let reg = /https?:\/\/(\w+\.)?(\w+\.)+(com|cn|org|cc)/gi ; console .log(mk2.match(reg)); </script >
matchAll 在新浏览器中支持使用 matchAll
操作,并返回迭代对象,返回由细节!
split 用于使用字符串或正则表达式分隔字符串,下面是使用字符串分隔日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <script > let mk2 = ` https: https: https: `; let reg = /https?:\/\/(\w+\.)?(\w+\.)+(com|cn|org|cc)/gi ; console .table(mk2.match(reg)); console .log(mk2.matchAll(reg)); for (const iterator of mk2.matchAll(reg)) { console .table(iterator); }; let mk = "2021/05/29" ; console .log(mk.split(/[\/-]/ )); </script >
replace replace
方法不仅可以执行基本字符替换,也可以进行正则替换,下面替换日期连接符
1 2 let str = "2023/02/12" ;console .log(str.replace(/\//g , "-" ));
1 2 3 4 5 6 <script > let mk = '(010)65313213 (020)3468621' ; let reg = /\((\d{3,4})\)(\d{7,8})/g ; console .log(mk.replace(reg, '$1-$2' )); </script >
替换字符串可以插入下面的特殊变量名:
变量
说明
$$
插入一个 “$”。
$&
插入匹配的子串。
$`
插入当前匹配的子串左边的内容。
$'
插入当前匹配的子串右边的内容。
$n
假如第一个参数是 RegExp
对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始
1 2 3 4 5 6 7 8 9 10 11 12 <script > let mk = '=%铁憨憨@=' ; console .log(mk.replace(/铁憨憨/ ,"==$&==" )); console .log(mk.replace(/铁憨憨/ ,"$`" )); console .log(mk.replace(/铁憨憨/ ,"$'" )); </script >
把所有准则
汉字加上链接 百度百科链接。
1 2 3 4 5 6 7 8 9 <body > <main > 核心价值观,简单来说就是某一社会群体判断社会事务时依据的是非标准,遵循的行为准则。 </main > </body > <script > const main = document .querySelector("body main" ); main.innerHTML = main.innerHTML.replace(/准则/g ,`<a href="https://baike.baidu.com/item%E6%A0%B8%E5%BF%83%E4%BB%B7%E5%80%BC%E8%A7%82/6946423?fr=aladdin">$&</a>` ); </script >
为链接添加上https
,并补全 www.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <body > <main > <a style ="color:red" href ="http://www.hdcms.com" > 开源系统 </a > <a id ="l1" href ="http://houdunren.com" > 后盾人</a > <a href ="http://yahoo.com" > 雅虎</a > <h4 > http://www.hdcms.com</h4 > </main > </body > <script > const main = document .querySelector("body main" ); const reg = /(<a.*href=['"])(http)(:\/\/)(www\.)?(hdcms|houdunren)/gi ; main.innerHTML = main.innerHTML.replace(reg, (v, ...args ) => { args[1 ] += "s" ; args[3 ] = args[3 ] || "www." ; return args.splice(0 , 5 ).join("" ); });</script >
把h标签全换成h4。
1 2 3 4 5 6 7 8 9 <script > let mk = ` <h1 > miketaylor</h1 > <span > 铁憨憨</span > <h2 > baidu</h2 > `; const reg = /<(h[1-6])>(?<con>.*?)<\/\1>/g ; console.log(mk.replace(reg,'<h4 > <con > <h4 > ')); </script >
使用原子组命名优化正则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <body > <main > <a href ="miketaylorjuly123.cn" > 个人站点</a > <a href ="www.baidu.com" > 百度</a > <a href ="www.google.com" > 谷歌</a > </main > </body > <script > const main = document .querySelector("body main" ); const reg = /<a.*?href=(["'])(?<link>.*?)\1>(?<title>.*?)<\/a>/gi ; const links = []; for (const iterator of main.innerHTML.matchAll(reg)){ links.push(iterator["groups" ]); } console .log(links); </script >
test方法
1 2 3 4 5 6 7 8 9 10 11 12 <body > <input type ="text" name ="email" > </body > <script > const mail = document .querySelector(`[name="email"]` ); mail.addEventListener("keyup" ,e => { let value = e.target.value; let flag = /^[\w-]+@(\w+\.)+(com|cn|cc|org)$/i .test(value); console .log(flag); });</script >
回调函数
replace 支持回调函数操作,用于处理复杂的替换逻辑
变量名
代表的值
match
匹配的子串。(对应于上述的$&。)
p1,p2, ...
假如replace()方法的第一个参数是一个 RegExp
对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)例如,如果是用 /(\a+)(\b+)/
这个来匹配,p1
就是匹配的 \a+
,p2
就是匹配的 \b+
。
offset
匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 'abcd'
,匹配到的子字符串是 'bc'
,那么这个参数将会是 1)
string
被匹配的原字符串。
NamedCaptureGroup
命名捕获组匹配的对象
使用回调函数将 后盾人
添加上链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <body > <div class ="content" > 后盾人不断更新优质视频教程 </div > </body > <script > let content = document .querySelector(".content" ); content.innerHTML = content.innerHTML.replace("后盾人" , function ( search, pos, source ) { return `<a href="https://www.houdunren.com">${search} </a>` ; });</script >
为所有标题添加上 hot
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <body > <div class ="content" > <h1 > 后盾人</h1 > <h2 > houdunren.com</h2 > <h1 > 后盾人</h1 > </div > </body > <script > let content = document .querySelector(".content" ); let reg = /<(h[1-6])>([\s\S]*?)<\/\1>/gi ; content.innerHTML = content.innerHTML.replace( reg, ( search, p1, p2, index, source ) => { return ` <${p1} class ="hot" >${p2}</${p1}> `; } );</script >
断言匹配 断言虽然写在扩号中但它不是组,所以不会在匹配结果中保存,可以将断言理解为正则中的条件。
(?=exp) 零宽先行断言 ?=exp
匹配后面为 exp
的内容
把后面是就
的miketaylor
加上链接
1 2 3 4 5 6 7 8 9 <main > miketaylor会不断学习,所以,只要坚持,miketaylor就会成为全栈! </main > </body > <script > let main = document .querySelector('body main' ); let reg = /miketaylor(?=就)/g ; main.innerHTML = main.innerHTML.replace(reg,`<a href ="http://miketaylorjuly123.cn" > $&</a > `); </script >
使用断言规范分数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script > let mk = ` Data Structure,90分 Computer Network,90分 Operation system,85.0分 Artificial Vision,100分 `; let reg = /(\d+)(.0)?(?=分)/gi ; let mk2 = mk.replace(reg, (v, ... args )=> { console .log(args); args[1 ] = args[1 ] || '.0' ; return args.splice(0 ,2 ).join('' ); }); console .log(mk2) </script >
使用断言验证用户名必须为五位,下面正则体现断言是不是组,并且不在匹配结果中记录。
1 2 3 4 5 6 7 8 9 10 11 12 <body > <input type ="text" name ="username" /> </body > <script > document .querySelector(`[name="username"]` ) .addEventListener("keyup" , function ( ) { let reg = /^(?=[a-z]{5}$)/i ; console .log(reg.test(this .value)); });</script >
(?<=exp) 零宽后行断言 ?<=exp
匹配前面为 exp
的内容
匹配miketaylor后面的数字
1 2 3 4 5 <script > let mk = "miketaylorjuly123.cn" ; let reg = /(?<=miketaylorjuly)\d+/i ; console .log(mk.match(reg)); </script >
所有超链接替换为https://miketaylorjuly123.cn
1 2 3 4 5 6 7 <script > const main = document .querySelector("main" ); let reg = /(?<=href=(['"])).+(?=\1)/ig ; main.innerHTML = main.innerHTML.replace(reg,"https://miketaylorjuly123.cn" ); </script >
使用断言模糊电话号码
1 2 3 4 5 6 7 8 9 10 11 12 <script > let users = ` 我的电话:15583703266 备用电话:15581664469 `; let reg = /(?<=\d{7})\d{4}/gi ; users = users.replace(reg , (v ) => { return '*' .repeat(4 ); }); console .log(users); </script >
获取标题中的内容
1 2 3 let hd = `<h1>我真的是铁憨憨</h1>` ;let reg = /(?<=<h1>).*(?=<\/h1>)/g ;console .log(hd.match(reg));
(?!exp) 零宽负向先行断言 后面不能出现 exp
指定的内容
使用 (?!exp)
字母后面不能为两位数字
1 2 3 4 5 <script > let mk = 'miketaylorjuly1232013dada' ; let reg = /[a-z]+(?!\d)$/i ; console .log(mk.match(reg)); </script >
断言限制用户关键词
1 2 3 4 5 6 7 8 9 10 <body > <input type ="text" name ="username" > </body > <script > const input = document .querySelector(`[name="username"]` ); input.addEventListener('keyup' , function ( ) { let reg = /^(?!.*加加林.*)[a-z]{5,6}$/i ; console .log(this .value.match(reg)) })</script >
(?<!exp) 零宽负向后行断言 前面不能出现exp指定的内容
获取前面不是数字的字符
1 2 3 4 5 6 7 <script > let mk = 'miketaylorjuly1232013dada' ; let reg = /(?<!\d+)[a-z]+/i ; let reg2 = /(?<!\d+).+/i ; console .log(mk.match(reg)); console .log(mk.match(reg2)); </script >
使用断言排除法同一数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <body > <main > <a href ="https://www.houdunren.com/1.jpg" > 1.jpg</a > <a href ="https://oss.houdunren.com/2.jpg" > 2.jpg</a > <a href ="https://cdn.houdunren.com/2.jpg" > 3.jpg</a > <a href ="https://houdunren.com/2.jpg" > 3.jpg</a > </main > </body > <script > const main = document .querySelector("main" ); const reg = /https:\/\/(\w+)?(?<!oss)\..+?(?=\/)/gi ; main.innerHTML = main.innerHTML.replace(reg, v => { console .log(v); return "https://oss.houdunren.com" ; });</script >
上完正则啦,感谢后端人教程UP主。