js 正则表达式-(学习笔记1)

148 阅读5分钟

体验正则表达式的魅力

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)) // ['张三', '李四']