let rg = /abc/
// /abc/ 只要测试字符串包含有abc这个字符串 返回的都是true
console.log(rg.test('abc')); //true
console.log(rg.test('abcd')); //true
console.log(rg.test('aabcd')); //true
let rg = /^abc/
// /^abc/ 只要测试字符串必须以abc开头
console.log(rg.test('abc')); //true
console.log(rg.test('abcd')); //true
console.log(rg.test('aabcd')); //false
let rg = /[abc]/ 只有包含有a或者包含有b或者包含有c 都返回true
let rg1 = /[abc]/
console.log(rg1.test('apple')) //true
console.log(rg1.test('color')) //true
//如果中括号里面有^ 表示取反的意思 千万和我们边界符 ^ 别混淆
let rg1 = /^[^a-z0-9A-Z_-]{1,}$/ //只有非数字字母下划线和短横线,test()才返回true
var reg = /^abc{3}$/ //它只是让c重复3次 想让abc重复3次 可以用()优先级
let price = '23.45'
let reg = new RegExp("\d+\.\d+")
console.log("\d+\.\d+"); //在字符串转义还是输出 d+.d+
console.log(reg.test(price)); //false 因为正则表达式的对象写法错了,要多加个\
let reg1 = new RegExp("\\d+\\.\\d+")
console.log("\\d+\\.\\d+"); //输出 \d+\.\d+
console.log(reg1.test(price)); //true
<input type="text" name="hh" id=""><span></span>
<script>
document.querySelector('[name="hh"]').addEventListener('keyup',function(){
let flag = this.value.match(/^[a-z]{3,6}$/i);
document.querySelector('span').innerHTML = flag ? '正确' : '失败'
})
</script>
let str = `
zjh
sb`
console.log(str.match(/.+/s)); //模式s能够匹配换行符"↵zjh↵sb"
- [\s\S] 或者[\d\D] 匹配所有字符
let str = `
#1 js,200元 #
#2 php,300元 #
#9 hdr.com # hdr
#3 node.js,180元 #
`
//{name:'js',price:'200元'}
// console.log(str.match(/^\s*#\d+\s+.+\s+#$/gm)); //m模式 每一行单独处理
let lessons = str.match(/^\s*#\d+\s+.+\s+#$/gm).map(value => {
//删除前后#
value = value.replace(/\s*#\d+\s*/,'').replace(/\s*#/,'')
let [name,price] = value.split(","); //数组解构
return {name,price}
})
console.log(JSON.stringify(lessons,null,2));
let str = 'zhengjiahao'
// console.log(str.match(/\w/g)); //输出数组,没有每个字符的位置信息
//使用正则的exec()方法改进不足
let reg = /\w/g
// console.log(reg.lastIndex); //0
// console.log(reg.exec(str)); //z
// console.log(reg.lastIndex); //1 当使用全局模式(g)才会记录上一次搜索的点,否则lastIndex永远是0
// console.log(reg.exec(str)); //h
while (res = reg.exec(str)) { //
console.log(res);
}
- 有效率的y模式
let str = 'people'
// let reg = /p/g
// console.log(reg.exec(str));// p
// console.log(reg.lastIndex);// 1
// console.log(reg.exec(str));// p
// console.log(reg.lastIndex);// 4
// console.log(reg.exec(str));// null
// console.log(reg.lastIndex);// 0
let reg = /p/y //y模式要求必须是连续满足条件,不然停止检索,g则可以跳过继续扫
console.log(reg.exec(str));// p
console.log(reg.lastIndex);// 1
console.log(reg.exec(str));// null
console.log(reg.lastIndex);// 0
- y模式的应用
let str = `福永图书馆QQ群:111111,999999,888888 办理借书证:
使用宝安图书馆公众号,电话咨询:86611111`
// 找出QQ群
let reg = /\d+,?/y
reg.lastIndex = 9 //默认是从0开始,必须修改,否则找不到
console.log(reg.exec(str)); //111111,
console.log(reg.exec(str)); //999999,
console.log(reg.exec(str)); //888888
console.log(reg.exec(str)); //null 停止检索(如果后面有大量的无关内容,这样y模式的确提高了效率)
let str = '2022-04-11'
let reg = /^\d{4}([-\/])\d{2}\1\d{2}$/ // \1 表示和([-\/])的匹配结果一致
console.log(str.match(reg));
let str = '张三:123456-00,李四:99999-11'
//1.找出中文字符
console.log(str.match(/[^:-\d,]+/g));
//2
console.log(str.match(/\p{sc=Han}+/gu));
- 在[( ) ],在中括号选项中,小括号被当做普通括号。放在[ ]外面才是原子组
let str = '(xixiaicangge).+\\'
let reg = /[\\.+]/g //在字符串. 和 + 就是普通的.和+
console.log(str.match(reg)); // [".", "+"]
let str = `
zhengjia
hao
`
console.log(str.match(/.+/g)); // [" zhengjia", " hao"] 碰到换行符就停掉
- 模式s : 忽略换行符
let str = `
zhengjia
hao
`
console.log(str.match(/.+/g))// [" zhengjia", " hao"] 碰到换行符就停掉
// [\s\S] 所有内容 [\d\D] 所有内容
console.log(str.match(/[\s\S]+/))
- 案例
<input type="text" name="hh" id=""><span></span>
<p>zhengjiahao</p>
<h1>age--18
height--190cm
</h1>
<h2>sex-man</h2>
<script>
//删除body里面的标题
let body = document.body;
// let reg = /<(h\d)>.+<\/\1>/gi //. 不能匹配换行符
let reg = /<(h\d)>[\s\S]*<\/\1>/gi //改进匹配所有内容
body.innerHTML = body.innerHTML.replace(reg,'')
</script>
- 如果某个内容要拿出来,就给个组,即外面加括号
let str = `
<h1>zheng</h1>
<span>jia</span>
<h2>hao</h2>
`
// 需求:把h标签替换为p标签
let reg = /<(h[1-6])>([\s\S]*)<\/\1>/gi
console.log(str.replace(reg,`<p>$2</p>`))
let str = `
<h1>zheng</h1>
<span>jia</span>
<h2>hao</h2>
`
// 需求:把h标签替换为p标签
let reg = /<(h[1-6])>(\w([\s\S]*))<\/\1>/gi
// console.log(str.replace(reg,`<p>$2</p>`))
let res = str.replace(reg,(p0,p1,p2,p3)=>{
// p0:整个匹配的字符串
// p1: 第一个原子组
// p2: 第二个原子组
// console.log(p0); //
// console.log(p1);
// console.log(p2); //zheng
// console.log(p3); //heng
return `<p>${p2}<p>`
})
let res = str.replace(reg,(p0,p1,p2,p3)=>`<p>${p2}<p>`)
console.log(res);
</script>
let str = `https://www.sina.com
http://tengxun.com
`
let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|org))/gi
//?: 表示不保留记录原子组,即\2用不了
let urls = []
while( res = reg.exec(str)){
urls.push(res[1])
}
console.log(urls);
<input type="text" name="password">
<script>
//需求:密码由5到10位的大小写字母和数字构成,且以字母或数字开头
let regs = [
/^[a-z0-9]{5,10}$/i,
/[A-Z]/,
/[0-9]/,
/[a-z]/,
]
document.querySelector(`[name="password"]`).onkeyup = e =>{
const val = e.target.value
//every 只有每个都为真,最终才是真
let state = regs.every(reg => reg.test(val)) //箭头函数省略了return
console.log(state ? '正确' : '错误');
}
</script>
- +和*的后面添加?可以禁止贪婪
- {2,100}?有多个时匹配2个
- ?? 一个问号是0到1个,后面再加括号时匹配0个
<main>
<span>深圳</span>
<span>福永图书馆</span>
</main>
<script>
let main = document.querySelector('main')
let reg = /<span>([\s\S]*?)<\/span>/gi
//[\s\S]包含所有字符,包括span,并且是贪婪的,所以会一直匹配到最后一个span
// 每匹配到一个,就执行一次该函数,value是匹配到字符串,p1是原子组\1
main.innerHTML = main.innerHTML.replace(reg,(value,p1) => {
return `<h4 style="color:red">Hello-${p1}</h4>`
})
// replace() 返回新一个字符串然后赋给main.innerHTML
<main>
<h1>深圳</h1>
<h2>福永图书馆</h2>
<h1>我在这里等你</h1>
</main>
<script>
// 需求:获取标签内的文字
const main = document.querySelector('main')
let reg = /<(h[1-6])>([\s\S]*?)<\/\1>/gi
// let res = main.innerHTML.match(reg) //g模式下输出
//["<h1>深圳</h1>", "<h2>福永图书馆</h2>", "<h1>我在这里等你</h1>"],没有出现原子组信息,去掉g才肯出现
let res = main.innerHTML.matchAll(reg) //迭代对象
//注意:低端浏览器没有这个matchAll()
let contents = []
//遍历
for(const item of res){
console.log(item);
contents.push(item[2])
}
console.table(contents)
//解决低端浏览器不支持matchAll()
String.prototype.matchAll = function(reg){
let res = this.match(reg)
if(res){
let str = this.replace(res[0],'^'.replace(res[0].length))
// console.log(str);
let match = str.matchAll(reg) || []
// console.log(match);
return [res,...match] //... 将数组展开
}
}
let str = 'zjhjia'
console.log(str.matchAll(/j/i));
- 使用exec 完成全局匹配
let main = document.querySelector('main').innerHTML
let reg = /<(h[1-6])>([\s\S]*?)<\/\1>/gi //注意使用exec一定要有g模式,否则lastIndex一直是0,不会接着上一次匹配位置
while(res = reg.exec(main)){
console.log(res);
}
console.log('zjh'.search('j')); //返回字符所在的索引 找不到返回-1
- match () 使用全局g模式时不带细节,所以需要细节,就改为matchAll(),这个方法返回迭代器对象
console.log(res = 'zjhjian'.matchAll(/j/g));
for(let item of res){
console.log(item);
}
const bir = '2020-09-11'
console.log(bir.split(/[-/]/)); //使用- 或者/ 拆分bir
console.log(bir.replace(/[-]/g,'/'));
// 需求:替换为 010-999999 020-8888888
let tel = '(010)999999 (020)8888888'
let reg = /\((\d{3,4})\)(\d{6,7})/g
// console.log(tel.match(reg));
console.log(tel.replace(reg,"$1-$2"));
// ?<= 前置断言
//找出前面是zheng的数字
let str = 'zheng123jia456'
let reg = /(?<=zheng)\d*/gi
console.log(str.match(reg));
<main>
<a href="http://www.lj1.com">链接1</a>
<a href="http://www.lj2.com">链接2</a>
</main>
<script>
//需求:将所有链接替换为http://www.baidu.com
let main = document.querySelector('main')
let reg = /(?<=href=(['"])).+(?=\1)/gi
// console.log(main.innerHTML.match(reg));
main.innerHTML = main.innerHTML.replace(reg,'http://www.baidu.com')
<main>
<a href="http://www.lj1.com">链接1</a>
<a href="http://www.lj2.com">链接2</a>
</main>
<script>
// 把号码后4位改为*
let user = `
我的电话:12345678901
我的QQ: 13664487310
`
let reg = /(?<=\d{7})\d{4}/gi //前置断言是非贪婪
// let reg = /\d{4}(?=(\d+))/gi //后置断言是贪婪
// user.replace(reg,(v,...args) => {
// console.log(v);
// console.log(args);
// })
console.log(user.replace(reg,'*'.repeat(4)))
- 断言虽然写在括号中,但他只是个条件,并不会像组一样出现在匹配结果中
- ?! 和 ?= 相反,表示后面不是
// 找到非数字结尾的字母串
let str = 'zheng123jia'
let reg = /[a-z]+(?!\d+)$/i
console.log(str.match(reg));
<input type="text" name="username">
<script>
//需求:用户名不能包含家豪
//从开始往后的内容不能包含家豪
let reg = /^(?!.*家豪.*)[a-z]{5,6}/i //^ 以字母开始
document.querySelector(`[name="username"]`).onkeyup = e =>{
console.log(e.target.value.match(reg));
}
// 找出前面不是数字的字母串
let str = 'zheng99jiahoa'
let reg = /(?<!\d+)[a-z]*/i
console.log(str.match(reg)); //zheng