加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

正则表达式总结

发布时间:2020-12-13 21:57:00 所属栏目:百科 来源:网络整理
导读:正则表达式( regular expression ) RegExp 用处: 匹配,验证; 替换,截取,分析 元字符 #### 基本元字符: 匹配任意的非换行字符,常常表示通用元字符使用 [sS] 匹配一个出现在 [] 中的字符,[123456789123456789123456789],[a-z0-9A-Z] 计算机只认识 数字,所以

正则表达式( regular expression )

  • RegExp
  • 用处: 匹配,验证; 替换,截取,分析

元字符

#### 基本元字符:

       匹配任意的非换行字符,常常表示通用元字符使用 [sS]
       匹配一个出现在 [] 中的字符,[123456789123456789123456789],[a-z0-9A-Z]
       计算机只认识 数字,所以我们写的字符串计算机其实不是以字符串的形式存储
                        有一个编码系统: unicode
                             '0'                 48
                             '1'                 49
                             ...
                             '9'                 57
                         写上:  '012',在内存中存储: 48 49 50 
                         需要记住的是:
                             '0'                 48
                             'a'                 97
                             'A'                 65
                             u0030
         ()              1> 分组; 2> 提升优先级
         |               或者
                         匹配 foot 或者 food
                         foot|food
                         注意: | 具有最低优先级
                         ^(foot|food)$
   - 常见的用法
                         例如要匹配jq的属性选择器: 
                         [name]
                         [name=value]
                         用正则: [w+=w+]|[w+]
                         jq 的写法: [w+(=w+|)] 
                         (foot|food)     匹配: 'foot' 或者 'food'
                         (foot|)         匹配: 'foot' 或者 ''
                         food(=food|)    匹配: 'food=food' 或者 'food'
                         w+(=w+|)      匹配: '字符=字符' 或 '字符'
                         [w+(=w+|)]  匹配: '[xxx]' 或 '[xxx=vvv]'
                         [s*(w+)s*(?:([|!^$~]?=)s*(w+)|)s*]
                         =>
                        [   s*     (w+)  s*   (?:   ([|!^$~]?=)     s*    (w+)   |)   s*   ]

#### 限定元字符

        +                   (abc)+              {1,}
        *                                       {0,}
        ?
        {n}
        {n,}
        {n,m}
#### 首尾元字符
        ^                   必须以 xxx 开头
                            表示否定:
                                [abc]           用来匹配 一个 字符 a,或 b,或 c
                                [^abc]          用来匹配一个字符,要求不允许是 a,b,c
        $                   必须以 xxx 结尾
                            表示组引用
                                a(b)c
#### 简写元字符
        w                  word
        W
        s                  space
        S
        d                  digit
        D
#### 其他:
        (?: )
        1

基本的匹配案例

如何匹配
    1) 匹配任意的自然数,就是 0,1,2,3,...
        [0-9]  等价于 d
        分类讨论
            -> 一位数字: d
            -> 两位: [1-9]d
            -> 任意位( 除了一位 ): [1-9]d+
        合并: 
            d|[1-9]d+
        可以进行演变( 用不同的方法写同一个例子 )
            [1-9]d*|0
            [1-9][0-9]*|0
            ...
    2) 匹配任意的整数,+1,-1,+2,-2,...
        [+-]?[1-9][0-9]*|0
        (+|-|)[1-9][0-9]*|0
        ...

    3) 匹配任意的实数,0.01,0.0000123,-0.1234567
        整数 + 小数部分
        分类( 划归 )
            ((+|-|)[1-9][0-9]*|0)(.d+|)

        无法匹配 -0.1
        无非就是不允许匹配 -0.0+

        使用正则的原则: 够用即可,尽可能写成多步的判断,要保证正则表达式的尽可能简洁
        -0+(.|)0*
        if ( !... ) {
            if ( ... )
        }
        d{17}|[dxX]
        d{11}

    4) 匹配邮箱
        [^@]+@[^@]+
        如果想要严谨一点
        邮箱分成用户名 和 域名
        用户名: 可以有数字,字母下划线组成( 还有一些特殊字符 )
            [w-]+
        域名: xxx.com.cn.xxxx
            [w-]+(.[w-]+)+

    5) 匹配 ip 地址
        采用数字点分的方法描述,而且每一个数字的取值在 0-255 之间,都可以取到
        0.0.0.0
        255.255.255.255
        123.124.125.126
        ...
        d{1,3}(.d{1,3}){3} 或者: d{1,3}.d{1,3} 

        利用正则实现匹配 0 到 255 的数字
        分类:
        一位: [0-9]
        两位: 10-99
              [1-9][0-9]
        三位: 100-255
              开始为 1 的: 100-199: 1[0-9][0-9]
              开始为 2 的: 200-255: 
                中间为 0-4 的: 2[0-4][0-9]
                中间为 5 的: 25[0-5]

        [0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]

        IP:
        [0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5].[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5].[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5].[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]

 - 如配匹配计算机中的一个文件路径全名
        例如: C:myMusicslistmyFavoriterain.MP3
            盘符: 一个字符: a-z,简单的写 . 如果想要严格处理 [a-z]
            冒号和斜线: :
            路径(文件夹的名字): .+ 如果想要精确: ([^|:?*></"]+)* 
            文件名: .+..+ 如果想要精确一点: [^|:?*></"]+.[^|:?*></"]+

            组合起来:
                .:.*.+..+
            注意: 正则表达式有贪婪模式
                 C:myMusicslistmyFavoriterain.MP3
                .:(.*).+..+
                .:.*.+.+
            如果一个正则表达式中有多个 .+ 或 .* 的结构,如果造成了匹配的歧义,满足一个规则. 即贪婪模式
            从左往右 匹配个数的能力是左强又弱,而且只有两个级别,要么强,要么弱

                例如: 
                    var s = '1234567890';
                    //        1 2 3
                    var r = /(.+)(.+)(.+)/;

                    var res = r.exec( s );
            例如匹配 div 标签
                    var r = /<div.*?>.*</div>/;
            如果不希望有贪婪模式在 限定元字符( +,* 等 )后写上 ?

字符串提取( 解析 )

.exec 方法
    利用正则表达式,去处理字符串,并将字符串中符合正则表达式的数据取出来 
    var s = '1234567';
    var r = /d/;
    var m = r.exec( s );   // m 是 match 的简写,表示捕获
    // 如果匹配上了,就返回数组,第 0 项 就是匹配到的结果,如果正则表达式中有 分组
    // 分组都是从 1 开始的编号,那么对应的 第 n 组匹配到的结果就在这个数组的第 n 项
    // 注意: 是真数组
    // 如果没有匹配到 则返回 null

    分组: 就是 ()
    从左往右数 (,第一个开始编号,从 1 开始编号,此时编号完成以后,对应圆括号组成的就是对应的组
    //         1   2  34       5
    例如: r = /(d)(d((d)d))(d)/;

    例子:获取网页中的QQ号: 
    想要做一个推广,在论坛中发布我有XXX的视频,如果想要的留下邮箱
    如果有人留下的是 QQ 号,将其拉到一个群里

    注意: exec 匹配提取,只能匹配提取第一个被捕获的数据
    如果需要匹配字符串中所有符合要求的字符串
    1) 开启全局模式,在正则后面写上一个 g,或在构造函数的 第二个参数中提供 'g'
        创建正则:
            -> 字面量:   /.+.+/g
            -> 构造函数: new RegExp( '.+\.+','g' )
    2) 开启全局模式后,使用 正则表达式对象 调用 exec 方法一次,就会从 0 位置或上一次结束的位置开始
        查找下一个匹配结果,如果查找到结果则返回对应数组,如果没有查找到( 即,找完了 )就会返回 null.
        如果还继续调用 exec,那么就从头开始再查一次.
    例如:
        var s = '123';
        var r = /d/g;

        r.exec( s );   // [ '1' ]
        r.exec( s );   // [ '2' ]
        r.exec( s );   // [ '3' ]
        r.exec( s );   // null
        r.exec( s );   // [ '1' ]
        ...

        一般要取到所有的数据,可以使用下面的代码结构
        var m;
        while ( ( m = r.exec( s ) ) != null ) {
            // 此时 m 就是找到的结果
        }

字符串替换

.replace( 正则表达式,需要替换的字符串 )
    1) 将一个字符串中所有的 - 换成一个连线
        var s = 'a-----------------------------------b----------------------c----d';
        // => a-b-c-d
        var res = s.replace( /-+/g,'-' );
        应用背景

            /*.*?([rn]+.*?)**/

        换行: rn
        因此 r 是回车的意思
             n 是换行的意思
        平时在处理换行的时候要注意: 在 有些时候是 rn,有些时候是 n
        在 类 Unix 操作系统中( unix,linux,mac ) 换行都是 n
        在 windows 中是 换行是 rn
    2) 在替换中还可以使用组
        var s = '2012-3-4';
        // 在不同的系统中想要显示成
        // 2012年3月4日
        // 3月4日2012年
        // 4/3/2012
        // ...
        var r = /(d+)-(d+)-(d+)/;

        var res = s.replace( r,'$1年$2月$3日' )
    3) 替换的时候,第二参数可以是函数,函数的参数为,匹配到的数组的散列值
        利用函数的返回值替换匹配到的结果

        var s = '2012-3-4';
        var r = /(d+)-(d+)-(d+)/;

        s.replace( r,function ( match,g1,g2,g3 ) { 
            return g1 + '年' + g2 + '月' + g3 + '日';
        });

        电话号码的加密
        var list = [
            '12345678901','12345678912','12345678923','12345678934','12345678945','12345678956'
        ];

        var res = list.map( function ( v ) {
            //                 电话号码的前4位
            //                              电话号码的后 2 位
            return v.replace( /(d{4})(d+)(d{2})/,function ( a,c,d ) {
                // a 就是匹配到的 电话号码
                // b 就是匹配到的 电话号码的前 4 位
                // c 就是匹配到的电话号码的 中间 5 位
                // d 就是匹配到的电话号码的 后 2 位
                return b + '***********'.slice( 0,c.length ) + d;
                // return b + '*****' + d;
            });
        });

    (?:)
    var s = '1234567';
    //        1   2       3     4
    var r1 = /(d)(ddd)(dd)(d)/;
    r1.exec( s ); // => [ '1234567','1','234','56','7' ]
    
    //        1             2     3
    var r2 = /(d)(?:ddd)(dd)(d)/;
    r2.exec( s ); // => [ '1234567','7' ]> 这里输入引用文本

希望对大家有帮助O(∩_∩)O~~

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读