体验正则表达式的魅力
1. 找出字符串中的数字
// 获取字符串中的数字
let hd = "houdunren2200hdcms9988"
// 不使用正则表达式
// parseInt('a') NaN
// 过滤出数字
let number = [...hd].filter(value => !Number.isNaN(parseInt(value)))
console.log(number.join("")) // 22009988
// 使用正则表达式
console.log(hd.match(/\d/g).join('')) // 22009988
2.字面量创建正则表达式
// 字面量创建正则表达式
let hd = 'houdunren.com'
console.log(/u/.test(hd)) // true
let a = 'u'
console.log(/a/.test(hd)) // false 无法识别变量
// 使用 eval 函数
console.log(eval(`/${a}/`).test(hd)) // true
小知识点:高亮匹配输入内容
<div>houdunren.com</div>
<script>
let con = window.prompt("请输入要检测的内容,支持正则表达式")
let reg = new RegExp(con, 'g')
let div = document.querySelector('div')
div.innerHTML = div.innerHTML.replace(reg, search => `<span style="color:red">${search}</span>`)
</script>
选择符的使用
let hd = "houdunren";
// "|": 或者
console.log(/a|@/.test(hd)) // false
console.log(/u|@/.test(hd)) // true
let tel = '010-9999999'
// 检测电话号码是北京或者上海
console.log(/010|020/.test(tel)) // true
let tel1 = '010'
console.log(/010\-\d{7,8}|020\-\d{7,8}/.test(tel1)) // false
// 使用原子组优化正则 /(010|020)/编为一组
let tel2 = '010-9999999'
console.log(/(010|020)\-\d{7,8}/.test(tel2)) // true
原子表和原子组中的选择符
// 原子表和原子组中的选择符
// [] ()
let reg = /[123456]/
// 1或2或3或4或5或6
let hd = '1'
console.log(reg.test(hd)) // true
console.log(hd.match(reg)) // ['1', index: 0, input: '1', groups: undefined]
let reg1 = /(12|34)/ // 12是个整体 或者 34
let str = '1212121'
let str1 = '88888822513'
console.log(str.match(reg1)) // ['12', '12', index: 0, input: '1212121', groups: undefined]
console.log(str1.match(reg1)) // null 匹配不成功
转义
// let price = 23.34;
// let price = '235785'
let price = '23@455'
// \d: 0-9
// \d+ "+" 1个或者多个
// 错误的写法 以上price都能被匹配
console.log(/\d+.\d+/.test(price)) // true
// . 表示:除换行外任何字符 以及 普通的字符点需要转义 \.
console.log(/\d+\.\d+/.test(price)) // false
// 使用对象创建正则
let reg = new RegExp('\\d+\\.\\d+')
console.log(reg.test(price))
// ? 代表: 0 个或者 多个
// "/" 斜杠的转义
let url = 'https://www.baidu.com'
console.log(/https?:\/\/\w+.\w+/.test(url)) // true
字符边界符约束
// 查找到字符串中有数字就为真,没有就为假,这显然不是我们想要的
// 就是匹配字符串中包含数字就为真,对它的边界没有做限定
let hd = 'aaa123'
console.log(/\d/.test(hd)) // true
// ^: 开始(限定起始边界) ------ ^\d 表示以数字开始
// $: 结束(限定结束边界) ------ \d$ 表示以数字结束
console.log(/^\d/.test(hd)) // false
console.log(/^\d$/.test(hd))
小案例:限制用户输入的用户名:3到6位的 a-z之间的字符
<input type="text" name="user">
<span></span>
<script>
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
let hd = "houdunren 2010"
// 获取字符串中的数字 g:全局匹配 +: 匹配一个或者多个
console.log(hd.match(/\d+/g)) // ['2010']
// 获取字符串中除了数字
console.log(hd.match(/\D+/g)) // ['houdunren ']
let str = `
张三:010-99999999,李四:020-8888888
`
// 获取字符串中的电话号码
console.log(str.match(/\d{3}\-\d{7,8}/g)) // ['010-99999999', '020-8888888']
// \d 表示0-9之间的数字, \D 表示除了数字
// 获取字符串中的中文
// [^] ^这个表示除了他们
// + 表示一个或者多个
// \s 表示空白字符(空白,空格,换行 tab符)
// \S 大写S 就表示 除了空白字符(空白,空格,换行 tab符)
console.log(str.match(/[^-\d:,\s]+/g)) // ['张三', '李四']
w 与 W 元字符
// \w : 字母,数字,下划线,也就是说已经揽括了 \d
let hd = 'houdunren2010'
console.log(hd.match(/\d+/g)) // ['2010']
let email = '44646464134@qq.com'
console.log(email.match(/^\w+@\w+\.\w+$/))
// \W 除了字母,数字,下划线
console.log('hdsldf@'.match(/\W/)) // @
点字符的使用
// \d: 表示0-9数字
// \w 表示字母,数字,下划线
// . 表示除了换行符之外的,任何字符(也就说包含\d和\w)
// + 表示 一个或者多个
let hd = "houdunren-#$@*"
console.log(hd.match(/.+/)) // 都能匹配到
let url = 'https://www.baidu.com'
console.log(url.match(/https?:\/\/\w+\.\w+\.\w+/))
// s 模式: 视为单行模式,只匹配一次
let h = `
houndunren.com
hdcms.com
`
console.log(h.match(/.+/s)[0])
/**
* houndunren.com
* hdcms.com
*/
// 匹配空格 (空格其实跟abc一样的也是普通字符)
let tel = "010 - 12345678"
console.log(tel.match(/\d+ - \d{8}/)) // 匹配
console.log(tel.match(/\d+\s-\s\d{8}/)) // 匹配
如何精巧的匹配所有字符
// [] 原子表
// \s 空白字符; \S 非空白字符
// [\s\S] [\d\D] 所有字符
let hd = `
<span>
houdunren @@@@
hdcms
</span>
`
console.log(hd.match(/<span>[\s\S]+<\/span>/)) // 匹配成功
console.log(hd.match(/<span>[\d\D]+<\/span>/))// 匹配成功
i 与 g 模式修正符
let hd = 'houdunren'
console.log(hd.match(/u/)) // 匹配成功
let hd1 = 'hoUdUnren' // U是大写的
console.log(hd1.match(/u/)) // 匹配失败
// i 模式: 忽略大小写(不区分大小写)
console.log(hd1.match(/u/i)) // 匹配成功 匹配到一个就停止了
// g 模式: 全局匹配(查找到结束为止)
// 模式可以组合使用, 前后顺序都可以的
console.log(hd1.match(/u/ig)) // ['U','U']匹配成功 -全部匹配出来了
// 替换字符串中的字符
console.log(hd1.replace(/u/gi, '@')) // ho@d@nren
m 多行匹配修正符
let hd = `
#1 js,200元 #
#2 php,300元 # 后盾人
#9 css,400元 #
#3 c,500元 #
#4 c++,600元 #
#10 node.js,700元 #
`
// 得到例如这样的数据: [{name: 'js', price: '200元'}]
// \s 匹配空白字符
// * 表示0次或者多次
// m模式表示多行匹配(每一行单独处理)
let lessons = hd.match(/^\s*#\d+\s+.+\s+#$/gm).map(v => {
v = v.replace(/\s*#\d+\s*/, '').replace(/\s+#/, '')
let [name, price] = v.split(',')
return {name, price}
})
console.log(lessons) // [{name: 'js', price: '200元'},....]
汉字与字符属性
// 任何字符都有相应的属性进行区分
// 比如说 a 字符有 [L] 属性,那就证明它是一个字母
let hd = 'houdunren2010'
// 匹配到所有的字母
console.log(hd.match(/\p{L}/gu)) // ['h', 'o', 'u', 'd', 'u', 'n', 'r', 'e', 'n']
let hd1 = 'houdunren2010.不断发布教程,加油!'
// 只匹配标点符号
console.log(hd1.match(/\p{P}/gu)) // ['.', ',', '!']
// 每个属性都有不同的特征 可以填写相应的字符属性找到相应的字符 查看 unicode.org文档
// Script 简写 sc 找到字符中的语言系统例如: sc=Han
let zn = 'houduneren 2010 , 我是中国人'
console.log(zn.match(/\p{sc=Han}/gu)) // ['我', '是', '中', '国', '人']
// PS: 有的字符是两字符,三个字符的宽字节 使用 u 模式
lastIndex属性的作用
// lastIndex属性是控制正则表达式开始搜索的位置
let hd = 'houdunren';
// 每次只能匹配第一个; 不能每个每个字符的往下找
// console.log(hd.match(/\w/)) // h
// console.log(hd.match(/\w/)) // h
// 使用 exec() 模式为 g 的使用才会记录上次的位置 才是有效的
let reg = /\w/g
// exec()会每个每个的字符开始走直到完成结束
// console.log(reg.lastIndex) // 0 从0开始搜索
// console.log(reg.exec(hd)) // h
// console.log(reg.lastIndex) // 1 从1开始搜索
// console.log(reg.exec(hd)) // 0
// 想保留字符串的主信息或者出现的位置,可以使用循环操作记录
// while((res = reg.exec(hd))) {
// console.log(res)
// }
有效率的 y 模式
// 模式 y 和 g 对比
let hd = 'udunren';
let reg = /u/g
// console.log(reg.exec(hd)) // u
// console.log(reg.lastIndex) // 1
// console.log(reg.exec(hd)) // u
// console.log(reg.lastIndex) // 3
// console.log(reg.exec(hd)) // null
// console.log(reg.lastIndex) // 0
// 由此可见 g模式下的exec()匹配会忽略不匹配的字符,玩下走
// y 模式下的exec() 不会忽略不匹配的字符 搜索停止结束了
let reg1 = /u/y
console.log(reg1.exec(hd)) // u
console.log(reg1.lastIndex) // 1
console.log(reg1.exec(hd)) // null
console.log(reg1.lastIndex) // 0
console.log(reg1.exec(hd)) // u
console.log(reg1.lastIndex) // 1
// y 模式下匹配大字符串内容,更有效率
// 匹配字符串中的qq号码
let h = `后盾人QQ群:11111111111,999999999,8888888,不断分析。网址:www.baidu.com`
// (\d+) 原子组 编为一组
let RegExp = /(\d+),?/y
// 改变lastIndex 从:后开始匹配
RegExp.lastIndex = 7
// console.log(RegExp.exec(h)) // 11111111111
// console.log(RegExp.exec(h)) // 999999999
// console.log(RegExp.exec(h)) // 8888888
// console.log(RegExp.exec(h)) // null
let qq = []
while((res = RegExp.exec(h))) {
qq.push(res[1])
}
console.log(qq) // ['11111111111', '999999999', '8888888']
原子表基本使用
let hd = 'houdunren'
// /ue/ 表示要完整的匹配 ue,必须是ue连着的两个字符串
console.log(hd.match(/ue/)) // null
// [] 中括号原子表 表示匹配[] 中的任何一个字符(u或者e任意一个字符都可以)
console.log(hd.match(/[ue]/g)) // ['u', 'u', 'e']
let tel = '2022-02-23' // 时间格式为:2022-02-23 或者 2022/02/23
// 使用原子表[-\/] 表示 - 或者 / ; "/" 需要转义 "\/"
console.log(tel.match(/^\d{4}[-\/]\d{2}[-\/]\d{2}$/)) // 都可以匹配成功
// 为了保证格式一致,不能为 2022-02/23 或者 2022/02-23
// 使用原子组更为严谨 把 ([-\/]) 编为一组 "\1"
// 后面的 \1 表示重复前面的 ([-\/]) 中的内容
console.log(tel.match(/^\d{4}([-\/])\d{2}\1\d{2}$/g)) // 匹配成功 更严谨
区间匹配
let hd= '2010'
console.log(hd.match(/\d+/g)) // ['2010']
console.log(hd.match(/[0-9]+/g)) // ['2010'] [0-9]升序,不能降序[9-0]报错
let hd1 = 'houdunren'
console.log(hd1.match(/[a-z]+/g)) // ['houdunren'] [a-z]升序写法,不能降序
排除匹配
let hd = 'houdunren.com'
console.log(hd.match(/[ue]/i))
// 排除匹配 在 [] 中添加 ^ 表示排除匹配([^ue])
// 匹配排除 ue 字符以外的所有字符
console.log(hd.match(/[^ue]/ig)) // ['h', 'o', 'd', 'n', 'r', 'n', '.', 'c', 'o', 'm']
// 匹配除了数字,: - , 以外的所有字符
let str = `张三:010-9999999,李四:010-8888888`
console.log(str.match(/[^\d:\-,]+/g)) // ['张三', '李四']
// 匹配中文
console.log(str.match(/\p{sc=Han}+/gu)) // ['张三', '李四']