美文网首页
[JavaScript学习笔记]正则表达式

[JavaScript学习笔记]正则表达式

作者: 这名字真不对 | 来源:发表于2017-06-05 01:14 被阅读0次

    常用

    作用:找到有规则的文本

    // 常用
    .   // 表示任意字符,不包括回车
    \n  // 回车
    \d  // 表示数字
    \b  // boundary 边界线,跟空格无关,而是词组的组成形式,英语是空格,中文是单字
    {n}  // n填数字,匹配前面的多个
    \w   // word,匹配字母数字或者下划线
    \s   // space 匹配空白符
    +   // 前面的字符一个或多个
    ^   // 开头
    $   // 结尾
    $1  // 需要放在替换栏,表示匹配到的字符保存下来,$1,$2… 对应前边第n个()包裹的东西 
    // 嵌套时从左到右看括号
    ?   // 可有可无  -?\d+  表示可有负号或者可以没有
    [ab]  // a或b
    \t   //水平制表符
    \v   //垂直制表符
    \n   //换行符
    \r   // 回车符
    \0   // 空字符
    \f   // 换页符
    \cX  // 与X对应的控制字符(Ctrl+x)
    

    修饰符

    • g : global 全局搜索
    • i : ignore case 忽略大小写
    • m : multiple lines 多行搜索

    默认下大小写敏感,且只匹配第一个匹配到的

    元字符

    * + ? ^ . | \ () {} []
    

    范围类

    表示一类,其中有一个即匹配,泛指某个特征的对象
    [a-z] 表示所有小写字母
    [a-zA-Z] 表示所有字母
    [abc] 表示abc归为一类,有其中一个
    ^负向类,字符类取反
    [^abc] 不包含a或b或c

    预定义类

    字符 等价类 含义
    . [^\r\n] 除了回车符和换行符之外的所有字符
    \d [0-9] 数字字符
    \s [\t\n\xOB\f\r] 空白符 space
    \S [^\t\n\xOB\f\r] 非空白符
    \w [a-zA-z_0-9] 单词字符(字母\数字\下划线)
    \W [^a-zA-z_0-9] 非单词字符
    \b 单词边界
    \B 非单词边界
    ^ 以xxx开始 判断依据是前面是否为空白符
    $ 以xxx主动放弃

    量词

    字符 含义
    ? 出现0次或1次(最多一次)
    + 出现1次或者多次(至少一次)
    * 出现0次或者多次(任意次)
    {n} 出现n次
    {n,m} 出现n到m次
    {n,} 至少出现n次

    贪婪匹配&懒惰匹配模式

    默认为贪婪模式,指有重复限定符时,匹配尽可能多的字符
    限定符后使用?则使用懒惰匹配

    懒惰匹配限定符

    代码/语法 说明
    *? 重复任意次,但尽可能少重复
    +? 重复1次或更多次,但尽可能少重复
    ?? 重复0次或1次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    {n,}? 重复n次以上,但尽可能少重复

    栗子

    贪婪模式

    '123456789'.replace(/\d{3,6}/,'x')
    // 'xxxxxx789'
    

    非贪婪模式下,会往最少的匹配

    '123456789'.match(/\d{3,6}?/g)
    // ['123','456','789']
    

    捕获(分组)

    // 自动命名分组
    (abc){3}  使量词作用域分组
    
    // 分组命名
    (?<name>exp)
    (?'name'exp) 命名为name的分组 
    
    // 不捕获(忽略分组)
    (?:abc).(ok)  // abc分组被忽略
    
    // 反向引用
    '2015-12-25'.replace(/(\d{4})-(\d{2})-(\d{2})/,'$2/$1/$3')  
    // 输出"12/25/2015"
    // 引用命名  
    \k<name>
    (?<abc>\d+)_\k<abc>\w+ 
    // 可以在同一个正则里面用,在JavaScript RegExp对象方法.replace两个参数里也可以使用用于替换
    

    零宽断言 (Lookahead and Lookbehind Zero-Length Assertions)

    • 前瞻即匹配到规则,向看(方向从文本末尾向开头称为)检查是否符合断言
    • 后顾/后瞻则相反
    • 正向(正预测/正回顾)指条件语句匹配
    • 负向相反

    需注意JavaScript不支持后顾

    名称 正则 含义
    正预测先行断言(正向前瞻) assert(?=exp) assert后面必须匹配exp条件
    负预测先行断言(负向前瞻) assert(?!exp) assert后面不能匹配exp条件
    正回顾后发断言(正向后顾) assert(?<=exp) JavaScript不支持
    负回顾后发断言(负向后顾) assert(?<!exp) JavaScript不支持

    JavaScript中构建方式 RegExp 对象

    字面量

    /\b\w/g
    // 斜杠之间为正则对象 斜杠右边为修饰符
    

    构造函数

    var reg = new RegExp('\\b\\w','g')
    // 两个参数 第一参数注意转义
    

    对象属性

    ignoreCase:返回一个布尔值,表示是否设置了i修饰符,该属性只读。
    global:返回一个布尔值,表示是否设置了g修饰符,该属性只读。
    multiline:返回一个布尔值,表示是否设置了m修饰符,该属性只读。
    lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
    source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。

    var reg = /abc/igm;
    reg.gloabl        // true 返回是否搜索全文 
    reg.ignoreCase    // true 返回是否大小写忽略
    reg.multiline     // true 返回是否多行匹配
    reg.lastIndex     //  0  返回索引位置
    reg.source        //  "abc"   返回正则表达式字符串形式
    

    对象方法

    RegExp.prototype.test()

    返回一个布尔值,表示是否匹配

    /apple/.test('牛顿吃苹果')  // false
    

    如果带g修饰符,则每一次test()都从上一次结束的位置开始向后匹配

    var reg = /a/g
    var string = "apple & apple" 
    reg.lastIndex // 0
    
    reg.test(string)  // true 匹配到第一个a
    reg.lastIndex // 1  位置是第一个
    
    reg.test(string)  // true 匹配到第二个a
    reg.lastIndex // 9  位置是第9个开始
    
    reg.test(string)  // false 匹配不到
    reg.lastIndex  // 0 匹配不到了
    
    reg.test(string)  // true 重新匹配到第一个
    reg.lastIndex  // 1 位置是第一个
    

    RegExp.prototype.exec(str)

    使用正则表达式模式对字符串进行搜索,并更新对象实例的属性,返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null。

    var s = 'cat'
    var r1 = /a/
    var r2 = /b/
    
    r1.exec(s)  // ["a"]
    r2.exec(s)  // null
    

    如果正则表示式包含圆括号()(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length属性等于组匹配的数量再加1。

    var s = '_x_x';
    var r = /_(x)/;
    
    r.exec(s) // ["_x", "x"]
    

    上面代码的exec()方法,返回一个数组。第一个成员是整个匹配的结果,第二个成员是圆括号匹配的结果,如果还有则继续匹配并返回到数组内

    同时该数组还包含两个属性,需要注意这个与正则实例对象的属性不同
    index 匹配成功的开始位置,从0开始计算
    input 整个远字符串

    var r = /a(p+)/
    var arr = r.exec('_apple pine apple')  // 是返回的数组才有属性
    arr      // ["app","pp"]
    arr.index // 1  位置是第二个
    arr.input // "_apple pine apple"
    

    如果使用修饰符g,下一次搜索会从上次成功匹配结束的位置开始

    var r = /a(p+)/g
    var s = 'apple pine pine apple pine'
    
    var a1 = r.exec(s)
    a1 //["app","pp"]
    a1.index // 0
    r.lastIndex // 3
    
    var a2 = r.exec(s)
    a2 //["app","pp"]
    a2.index // 16
    r.lastIndex // 19
    
    // 如果匹配不到了
    var a3 = r.exec(s)
    a3 // null
    a3.index // TypeError: Cannot read property 'index' of null
    r.lastIndex // 0
    
    // 循环了
    var a4 = r.exec(s)
    a4 //["app","pp"]
    a4.index // 0
    r.lastIndex // 3
    

    由于其存在循环的情况,我们利用返回的数组判断循环结束,一次循环完成所有匹配

    var r = /a(b+)a/g;
    var s = '_abbba_aba_';
    
    while(true) {
      var match = r.exec(s);
      if (!match) break; //当数组结果不存在时就跳出循环
      console.log(match[1]);  
    }
    // bbb
    // b
    

    如果设置了lastIndex属性,就会从lastIndex位置开始匹配,需要g修饰符才生效

    var r1 = /a(p+)/
    r1.lastIndex = 5 
    var a1 = r1.exec('apple pine apple')
    a1.index  // 0
    r1.lastIndex // 3
    // 由于没有g 所以无效
    
    var r2 = /a(p+)/g
    r2.lastIndex = 5 
    var a2 = r2.exec('apple pine apple')
    a2.index  // 11
    r2.lastIndex // 14
    // 有g修饰符,所以生效
    

    字符串对象方法 search() | match() | replace() | split()

    search()

    返回匹配结果的在字符串中的位置,g修饰符无效,因此lastIndex属性也无效

    'apple pine apple'.search(/a(p+)/)
    // 0  
    // 第一个位置,从0 开始数
    'apple pine apple'.search(/bba/)
    // -1 
    // 没匹配到
    
    var r = /a(p+)/g;
    r.lastIndex = 5; // 无效
    'apple pine apple'.search(r) // 0
    

    match()

    返回匹配成功的的结果的数组,失败则返回null,g无效

    var s = 'apple pine'
    s.match(/a(p+)/)  // ["app", "pp"]
    s.match(/b(a+)/)  // null
    
    var r = /a(p+)/g 
    r.lastIndex = 5
    s.match(r)  // ["app", "pp"]
    r.lastIndex  // 0 
    // g修饰符无效
    

    replace()

    接受两个参数,第一个为搜索模式,第二个为替换内容,有g修饰符时替换所有字符

    var s = 'apple'
    s.replace(/p/,'b') // "abple"
    s.replace(/p/g,'b') // "abble"
    
    // 清除字符串两端空白符
    var str = '  #id div.class  ';
    str.replace(/^\s+|\s+$/g, '')
    // "#id div.class"
    

    replace()方法的第二个参数可以使用美元符号$,用来指代所替换的内容

    $& 指代匹配的子字符串。
    $` 指代匹配结果前面的文本。
    $' 指代匹配结果后面的文本。
    $n 指代匹配成功的第n组内容,n是从1开始的自然数。
    $$ 指代美元符号$。
    
    'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
    // "world hello"
    
    'abc'.replace('b', '[$`-$&-$\']')
    // "a[a-b-c]c"
    

    第二个参数还可以是函数,将匹配内容替换为函数返回值
    该函数可接受多个参数,第一个为捕捉的内容match,第二个为第二个参数是捕捉到的组匹配(有多少个组匹配,就有多少个对应的参数)。此外,最后还可以添加两个参数,倒数第二个参数是捕捉到的内容在整个字符串中的位置(比如从第五个位置开始),最后一个参数是原字符串。

    var prices = {
      'pr_1': '$1.99',
      'pr_2': '$9.99',
      'pr_3': '$5.00'
    };
    
    var template = '/* ... */'; // 这里可以放网页模块字符串
    
    template.replace(
      /(<span id=")(.*?)(">)(<\/span>)/g,
      function(match, $1, $2, $3, $4){
        return $1 + $2 + $3 + prices[$2] + $4;
      }
    );
    

    split()

    字符串对象按正则规则分割,返回分割后组成的数组,接受两个参数,第一个为分割规则,第二个为最大成员数

    // 非正则分隔
    'a,  b,c, d'.split(',')
    // [ 'a', '  b', 'c', ' d' ]
    
    // 正则分隔,去除多余的空格
    'a,  b,c, d'.split(/, */)
    // [ 'a', 'b', 'c', 'd' ]
    
    // 指定返回数组的最大成员
    'a,  b,c, d'.split(/, */, 2)
    [ 'a', 'b' ]
    
    // 组匹配成员也会返回到数组
    'aaa*a*'.split(/(a*)/)
    // [ '', 'aaa', '*', 'a', '*' ]
    

    参考:

    http://javascript.ruanyifeng.com/stdlib/regexp.html
    https://regexper.com/
    http://www.regular-expressions.info/lookaround.html

    相关文章

      网友评论

          本文标题:[JavaScript学习笔记]正则表达式

          本文链接:https://www.haomeiwen.com/subject/knobfxtx.html