js正则表达式(二)
原子表[]
原子表只代表一个字符
let hd='houdunren';
console.log(hd.match(/ue/)); // 这个表示整个ue,连在一起的ue
console.log(hd.match(/[ue]/g)); // 这个表示u或e,是[xxx]中的单个字符,按单一匹配
// 这里有一个日期的例子
let str='2021-11-29'
let reg=/^\d{4}([-\/])\d{2}\1\d{2}$/
console.log(reg.test(str)); // true
str='2021/11/29';
console.log(reg.test(str)); // true
str='2021/11-29';
console.log(reg.test(str)); // false
区间匹配 -
-:子区间的意思
let hd='houdunren'
// 匹配过程:h满足,放起来;o满足,放起来……
console.log(hd.match(/[a-z]/g)); // ['h','o',...]
// 加上+就贪婪了:满足满足满足会将最后变成一个整体
console.log(hd.match(/[a-z]+/g)); // ['houdunren']
排除匹配 ^
let hd='张三:010-88888888,李四:021-77777777'
console.log(hd.match(/[^:\d\-,]+/g))
console.log(hd.match(/\p{sc=Han}+/gu))
特殊字符不解析
在原子表中,字符只是保留字符本意。
let hd='(houdunren).+'
console.log(hd.match(/[().+]+/g)) // 只是保留字符本意
小技巧:如何匹配所有字符
let hd=`
houdunren
angela
`
console.log([...hd]);
// 1.使用.*结合s模式
console.log(hd.match(/.*/s));
// 2.[\s\S] x和非x结合起来
console.log(hd.match(/[\s\S]+/));
正则操作dom~这个例子很有意思
题意:去掉html中的h标签,即h1-h6
这里有3个点很重要:
-
首先是匹配标签中的所有内容。上一个小技巧讲过
-
使用分组。因为前后标签一定要是匹配的,所以后面一定要使用分组。<h[1-6]>...<\/\1>
-
要使用.*?这种懒惰模式。匹配到最近的闭合标签。
let htmlStr=document.body.innerHTML;
console.log('---')
// 去掉script标签
console.log(htmlStr.match(/<script (.*?)<\/script>/sg))
htmlStr=htmlStr.replace(/<script (.*?)<\/script>/gsi,'')
console.log('开始---')
console.log(htmlStr)
// 关键的一句正则在这里
htmlStr=htmlStr.replace(/<(h[1-6])>.*?<\/\1>/gsi,'')
console.log(htmlStr)
document.body.innerHTML=htmlStr;
这里有一个扩展:懒惰模式
在 .* 或者 .+ 后面,加上一个?,就表示懒惰模式。我匹配到第一个就不再往后匹配了,即最小匹配。
等于:后面跟一个?表示懒惰模式。它是必须跟在 * 或者 + 后面用
正则表达式-- (.*?) 或 (.*+)_Scarlett-优快云博客
https://www.jb51.net/article/187050.htm
原子组()
用括号包裹的就是原子组,自动为每个组进行编号,引用分组 \1 \2 ......
let str=`
<h1>regexp</h1>
<h2>js</h2>
`
let reg=/<(h[1-6])>([\s\S]*)<\/\1>/i;
console.log(str.match(reg))
邮箱中的简单匹配
正则语法不难,考虑细一点,方方面面都要想到
let str=`adjejing@qq.com`
let reg=/^[\w-]+@([\w-]+\.)+\.(com|cn|cc|net|org)$/;
console.log(str.match(reg))
使用原子组完成替换
如果你想把某个内容拿出来你就把它变成一个组,用$1 $2去拿到它
str.replace(reg,(match,$1,$2,$3,index,input)=>{ ... }
这里补充一下replace function的参数:
-
第一个是匹配到的字符串
后面就是各个分组,无分组则没有
-
$1
-
$2
-
$3
......
-
index,匹配到字符串在整个字符串中的位置
-
input,整个字符串
我们惊奇地发现,同str.match(非/g模式)方法返回的数组的元素是一样的
额外:括号套括号的情况,数的话从边上开始数, 从左括号边开始数
let str=`
<h1>hello angela</h1>
<h1>连续的h1</h1>
<h2>hello regexp</h2>
<p>regexp</p>
`
let reg=/<(h[1-6])>([\s\S]*?)<\/\1>/gi;
str=str.replace(reg,(match,$1,$2,$3)=>{
console.log('---')
console.log(match)
console.log($1)
console.log($2)
console.log($3)
return `<p>${$2}</p>`
})
console.log(str);
获取url:非捕获分组和嵌套分组
?: 非捕获分组。无法使用$1 \1 以及match、exec中都不会有相关输出
嵌套分组:括号套括号的情况,数的话从边上开始数, 从左括号边开始数
let str=`
https://www.baidu.com
http://houdunren.com
https://jsrun.org
`
let reg=/https?:\/\/((?:\w.)+(?:com|cn|org))/g;
console.log(str.match(reg))
let urls=[]
let res;
while(res=reg.exec(str)){
urls.push(res[1])
}
console.log(urls);
重复匹配(结合分组)
符号* + { , }:这个再熟悉不过了,即贪婪模式。它们都是贪婪的,尽可能多,越多越好
(abc)+:如果说前面有分组,那么贪婪是针对于整个分组的
电话号码例子
let str=`010-88888888`
// 以0开头,前面304位,-后面7-8位
let reg=/^0\d{2,3}-\d{7,8}$/
console.log(str.match(reg))
用户名例子
let str=`angela95`
// 以0开头,前面304位,-后面7-8位
let reg=/^[a-z][\w-]{2,7}$/i
console.log(str.match(reg))
密码的例子
有时候一个数据会需要多个正则进行校验,我们可以把正则做到数组里面,然后使用regs.every
let password=`angelA95`
let iscorrect='错误'
// 由字母和数字组成,必须包含一个大写字母
if(/^[a-z0-9]{5,10}$/i.test(password) && /[A-Z]/.test(password) && /[0-9]/.test(password)){
iscorrect='正确'
}
console.log(iscorrect)
// 下面的做法语法更漂亮
const regs=[/^[a-z0-9]{5,10}$/i,/[A-Z]/,/[0-9]/]
// every:全都为真的时候,整个表达式为真
console.log(regs.every(reg=>reg.test(password)))
懒惰模式,即禁止贪婪
在限定词后面加上问号?,就表示禁止贪婪,即懒惰模式。
我匹配到最近的一个就不往后匹配了,立即停止。
这里有一个典型的懒惰模式的例子~~~
let str=`
<span>houdunren</span>
<span>houdun.com</span>
<span>hdrjy</span>
`
let reg=/<span>([\s\S]*?)<\/span>/g
str=str.replace(reg,`<h4 style="color:red">后盾人-$1</h4>`)
console.log(str)
document.body.innerHTML=str;
如果 reg=/<span>([\s\S]*)<\/span>/g
那么它会匹配到最后一个</span>闭合标签,因为其实中间所有的内容都满足[\s\S],*是贪婪的,所以并不是我们想要的;
所以要加上? reg=/<span>([\s\S]*?)<\/span>/g
禁止贪婪使其匹配到最近的一个闭合标签</span>