正则表达式(1)

146 阅读5分钟

先贴一份正则常用的规则。

元字符	 说明	                                              示例
\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: \. 普通点   


修饰符	  说明
i	    不区分大小写字母的匹配
g	    全局搜索所有匹配内容
m	    视为多行
s	    视为单行忽略换行符,使用. 可以匹配所有字符
y	    从 regexp.lastIndex 开始匹配
u	    正确处理四个字符的 UTF-16 编码



原子表   说明
[]	只匹配其中的一个原子
[^]	只匹配"除了"其中字符的任意一个原子
[0-9]	匹配 0-9 任何一个数字
[a-z]	匹配小写 a-z 任何一个字母
[A-Z]	匹配大写 A-Z 任何一个字母


原子组
变量     说明
0	匹配到的完整内容
1,2....	匹配到的原子组
index	原字符串中的位置
input	原字符串
groups	命名分组

实战练习

  1. 查出所有的数字
        let hd = "houdunren2200hdcms9988";
        console.log(hd.match(/\d/g));//['2', '2', '0', '0', '9', '9', '8', '8']
  1. 创建正则 & 变量使用
        创建正则 & 变量使用
        let hd = "houdunren.com";
        console.log(/u/.test(hd));//true
        const key = 'u'
        console.log(/key/.test(hd));//false
        console.log(eval(`/${key}/`).test(hd));
        对象创建
        let hd = "houdunren.com";
        let web = "houdunren";
        let reg = new RegExp(web);
        console.log(reg.test(hd));

  1. 高亮字符
        <div id="content">houdunren.com</div>

        3. 高亮字符
        const content = prompt("请输入要搜索的内容,支持正则表达式");
        const reg = new RegExp(content,'g')
        const dom = document.getElementById('content')
        dom.innerHTML = dom.innerHTML.replace(reg,str=>{
            return `<span style="color:red">${str}</span>`
        })
  1. 选择符, | 这个符号带表选择修释符,也就是 | 左右两侧有一个匹配到就可以。 检测电话是否是上海或北京的坐机
        let tel = "010-12345678"; // let tel = "010-1";
        //错误结果:只匹配 | 左右两边任一结果 "010"
        console.log(tel.match(/010|020\-\d{7,8}/));// 010-12345678  |  010
        //正确结果:所以需要放在原子组中使用
        console.log(tel.match(/(010|020)\-\d{7,8}/));// 010-12345678
  1. 字符转义
        假如有这样的场景,如果我们想通过正则查找/符号,但是 /在正则中有特殊的意义。
        如果写成///这会造成解析错误,所以要使用转义语法 / \/ /来匹配。
        
        const url = "https://www.houdunren.com";
        console.log(/https:\/\//.test(url))//true
        console.log(/^https?:\/\/\w+\.\w+\.\w+$/.test(url));//true
        
        
        使用 RegExp 构建正则时在转义上会有些区别,下面是对象与字面量定义正则时区别
        
        let price = 12.23;
        //含义1: . 除换行外任何字符 	含义2: \. 普通点
        //含义1: d 字母d   		含义2: \d 数字 0~9
        console.log(/\d+\.\d+/.test(price));
        //字符串中 \d 与 d 是一样的,所以在 new RegExp 时\d 即为 d
        console.log("\d" == "d");// true
        //使用对象定义正则时,可以先把字符串打印一样,结果是字面量一样的定义就对了
        console.log("\\d+\\.\\d+");
        let reg = new RegExp("\\d+\\.\\d+");
        console.log(reg.test(price));
  1. 字符边界
        使用字符边界符用于控制匹配内容的开始与结束约定。
        边界符	说明
        ^	匹配字符串的开始
        $	匹配字符串的结束,忽略换行符

        const hd = "www.houdunren.com";
        console.log(/^www\.\w+\.com$/.test(hd)); //true

        检测用户名长度为 3~6 位,且只能为字母。如果不使用 ^与$ 限制将得不到正确结果
        document
        .querySelector(`[name="username"]`)
        .addEventListener("keyup", function() {
        let res = this.value.match(/^[a-z]{3,6}$/i);
        console.log(res);
        console.log(res ? "正确" : "失败");
        });
  1. 元子字符
        元字符	说明	                                    示例
        \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: \. 普通点  
        
        
        匹配任意数字
        let hd = "houdunren 2010";
        console.log(hd.match(/\d/g)); //["2", "0", "1", "0"]

        匹配所有电话号码
        let hd = `张三:010-99999999,李四:020-88888888`;
        let res = hd.match(/\d{3}-\d{7,8}/g);
        console.log(res);
       
        获取所有用户名
        let hd = `张三:010-99999999,李四:020-88888888`;
        let res = hd.match(/[^:\d-,]+/g);
        console.log(res);

        匹配任意非数字
        console.log(/\D/.test(2029)); //false

        匹配字母数字下划线
        let hd = "hdcms@";
        console.log(hd.match(/\w/g)); //["h", "d", "c", "m", "s"]

        匹配除了字母,数字或下划线外与任何字符匹配
        console.log(/\W/.test("@")); //true

        匹配与任意一个空白字符匹配
        console.log(/\s/.test(" ")); //true
        console.log(/\s/.test("\n")); //true

        匹配除了空白符外任意一个字符匹配
        let hd = "hdcms@";
        console.log(hd.match(/\S/g)); // ['h', 'd', 'c', 'm', 's', '@']

        如果要匹配点,则需要转义
        let hd = `houdunren@com`;
        console.log(/houdunren.com/i.test(hd)); //true    含义1. 除换行外任何字符 	含义2: \. 普通点
        console.log(/houdunren\.com/i.test(hd)); //false

        使用.匹配除换行符外任意字符,下面匹配不到hdcms.com 因为有换行符
        const url = `
            https://www.houdunren.com
            hdcms.com
            `;
        console.log(url.match(/.+/)[0]);//            https://www.houdunren.com


        使用/s视为单行模式(忽略换行)时,. 可以匹配所有
        let hd = `
            <span>
                houdunren
                hdcms
            </span>
            `;
        console.log(hd.match(/<span>.*<\/span>/s)[0]);    


        正则中空格会按普通字符对待
        let tel = `010 - 999999`;
        console.log(/\d+-\d+/.test(tel));    
        console.log(/\d+ - \d+/.test(tel)); 
        console.log(/^\d{3} - \d{6}$/.test(tel));       


        所有字符  可以使用 [\s\S] 或 [\d\D] 来匹配所有字符
        let hd = `
            <span>
                houdunren
                hdcms
            </span>
            `;
        console.log(hd.match(/[\s\S]+/)[0]);  
  1. 模式修饰
        修饰符	    说明
        i	    不区分大小写字母的匹配
        g	    全局搜索所有匹配内容
        m	    视为多行
        s	    视为单行忽略换行符,使用. 可以匹配所有字符
        y	    从 regexp.lastIndex 开始匹配
        u	    正确处理四个字符的 UTF-16 编码

        i 将所有houdunren.com 统一为小写
        let hd = "houdunren.com HOUDUNREN.COM";
        hd = hd.replace(/houdunren\.com/gi,'houdunren.com')
        console.log(hd);

        g 使用 g 修饰符可以全局操作内容
        let hd = "houdunrenuuu";
        hd = hd.replace(/u/,'@')
        console.log(hd);//ho@dunrenuuu
        hd = hd.replace(/u/g,'@')
        console.log(hd);//ho@d@nren@@@


        m 用于将内容视为多行匹配,主要是对 ^和 $ 的修饰
        let hd = `
        #1 js,200元 #
        #2 php,300元 #
        #9 houdunren.com # 你爷爷
        #3 node.js,180元 #
        `;
        const res = hd.match(/^\s*#\d+\s+.+\s+#$/gm).map(v =>{
           v = v.replace(/^\s*#\d+\s+/,'').replace(/^\s+#\s*/,'')
           const [name,price] = v.split(',')
           return {name,price}
        })
        console.log(res);



        u 每个字符都有属性,如L属性表示是字母,P 表示标点符号,需要结合 u 模式才有效。其他属性简写可以访问 属性的别名 
        使用\p{L}属性匹配字母
        let hd = "houdunren2010.不断发布教程,加油!";
        console.log(hd.match(/\p{L}+/gu)[0]);//"houdunren"
        使用\p{P}属性匹配标点
        console.log(hd.match(/\p{P}+/gu));


        lastIndex
        RegExp 对象lastIndex 属性可以返回或者设置正则表达式开始匹配的位置
        必须结合 g 修饰符使用
        对 exec 方法有效
        匹配完成时,lastIndex 会被重置为 0

        let hd = `后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
        let reg = /后盾人(.{2})/g;
        reg.lastIndex = 10; //从索引10开始搜索
        console.log(reg.exec(hd));
        console.log(reg.lastIndex);


        let hd = `后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
        reg = /\p{sc=Han}/gu;
        while(res = reg.exec(hd)){
            console.log(res);
        }




        y 我们来对比使用 y 与g 模式,使用 g 模式会一直匹配字符串
        但使用y 模式后如果从 lastIndex 开始匹配不成功就不继续匹配了
        let hd = "udunren";
        let reg = /u/y;
        console.log(reg.exec(hd));
        console.log(reg.lastIndex); //1
        console.log(reg.exec(hd)); //null
        console.log(reg.lastIndex); //0

        因为使用 y 模式可以在匹配不到时停止匹配,在匹配下面字符中的 qq 时可以提高匹配效率
        let hd = `后盾人QQ群:11111111,999999999,88888888后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
        let reg = /(\d+),?/y;
        reg.lastIndex = 7;
        while ((res
  1. 原子表
原子表	 说明
[]	    只匹配其中的一个原子
[^]	    只匹配"除了"其中字符的任意一个原子
[0-9]	匹配 0-9 任何一个数字
[a-z]	匹配小写 a-z 任何一个字母
[A-Z]	匹配大写 A-Z 任何一个字母

    使用[]匹配其中任意字符即成功,下例中匹配ue任何一个字符,而不会当成一个整体来对待
    const url = "houdunren.com";
    console.log(/ue/.test(url)); //false
    console.log(/[ue]/.test(url)); //true

    日期的匹配 *** ([-\/])   \1   原子组
    let tel = "2022-02-23";  //"2022-02/23"; 
    let reg = /^\d{4}([-\/])\d{2}\1\d{2}$/
    console.log(tel.match(reg),reg.test(tel)); 


    const num = "2";
    console.log(/[0-3]/.test(num)); //true
    const hd = "e";
    console.log(/[a-f]/.test(hd)); //true

    ^的使用 -- 排除匹配
    let hd = `
    张三:010-99999999,李四:020-88888888`;
    let res = hd.match(/[^:\d-,\s]+/g);
    console.log(res);


    原子表中有些正则字符不需要转义,如果转义也是没问题的,可以理解为在原子表中. 就是小数点
    let str = "(houdunren.com)+";
    console.log(str.match(/[(+.]/gi));//['(', '.', '+']

    可以使用 [\s\S] 或 [\d\D]匹配到所有字符包括换行符
    let hd = `
            qqq
            ddd

    `
    const reg = /[\s\S]+/g;
    console.log(hd.match(reg));

    原子删除 h 元素
    const body = document.body
    const reg = /<(h[1-6])>[\s\S]*<\/\1>/g
    let content = body.innerHTML.replace(reg,'')
    body.innerHTML = content
  1. 原子组
    如果一次要匹配多个元子,可以通过元子组完成
    原子组与原子表的差别在于原子组一次匹配多个元子,而原子表则是匹配任意一个字符
    元字符组用 () 包裹
    下面使用原子组匹配 h1 标签,如果想匹配 h2 只需要把前面原子组改为 h2 即可。

    原子组
    const hd = `<h1>houdunren.com</h1>`;
    console.log(/<(h1)>.+<\/\1>/.test(hd)); //true

    邮箱验证
    const email = '1212@hd.com.cn'
    let reg = /^[\w-]+@([\w-]+\.)+(org|com|cc|cn)+$/
    console.log('email',reg.test(email));

    引用分组
    在匹配时引用原子组, $n 指在替换时使用匹配的组数据。下面将标签替换为p标签

    let hd = `
    <h1>houdunren</h1>
    <span>后盾人</span>
    <h2>hdcms</h2>
    `;
    let reg = /<(h[1-6])>([\s\S]*)<\/\1>/gi;
    console.log(hd.replace(reg, `<p>$2</p>`));