正则表达式与其匹配规则

  1. 字面量字符和元字符

    大部分字符在正则表达式中,就是字面的含义,比如 /a/ 匹配 a , 就像这种,字符只表示它字面的含义,那么它们就叫做”字面量字符”

    /dog/.test(‘old dog’) // true

    除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思,被称为元字符,主要有以下几个:

    (1) 点字符 (.)

    点字符匹配 除了回车(\r) 换行(\n) 分隔符(\u2028) 和段分隔符 (\u2029) 以外的所有字符.但是对于码点大于0xFFFF字符,点字符不能正确匹配,会认为是两个字符.

    (2) 位置字符

    位置字符用来提示字符所处的位置,主要有两个字符

    • ^ 表示字符串的开始位置

    • $ 表示字符串的结束位置

      /^text/.test(’text123’) // true
      /text$/.test(‘123text’) // true
      /^text$/.test(’text’)  // true
      

    (3) 选择符(|)

    在正则表达式中表示”或关系"(OR),也就是 cat|dog 表示匹配cat 或者 dog

    其它的元字符还包括

    \  \* +  ?  () [] {} 等
    
  2. 转义字符

    正则表达式中对于上面那些元字符来说,如果匹配它们本身,就需要在它们前面加上反斜杠.比如要匹配+ 就要写成 \+

    /1+1/.test('1+1') //false
    /1\+1/.test('1+1') //true
    

    正则表达式中,需要反斜杠转义的,一共有12个字符:^.[$()|*+?{\。需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

  3. 特殊字符

    正则表达式对一些不能打印的特殊字符,提供了表达方法。

    • \cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
    • [\b] 匹配退格键(U+0008),不要与\b混淆。
    • \n 匹配换行键。
    • \r 匹配回车键。
    • \t 匹配制表符 tab(U+0009)。
    • \v 匹配垂直制表符(U+000B)。
    • \f 匹配换页符(U+000C)。
    • \0 匹配null字符(U+0000)。
    • \xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
    • \uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。
  4. 字符类

    字符类 (class) 表示有一系列字符可供选择,只要匹配其中一个就可以了,所有可供选择的字符都放在方括号内,比如 [xyz] 表示x,y,z 任何一个匹配上就行.

    /[abc]/.test('hello world') //false
    /[abc]/.test('apple')  //true
    

    有两个字符在字符类中有特殊含义

    (1) 脱字符 (^)

    如果[ ] 内的第一个字符是 ^,则表示除了字符类这中的字符,其它字符都可以匹配. 比如

    [^xyz] 表示除了 x y z 之外都算匹配成功
    
    /[^abc]/.test('bbc news') //true
    //bbc news 包含除了abc之外的字符,所以匹配成功
    /[^abc]/.test('bbc') //false
    //bbc 中不包含除了abc之外的字符,匹配失败
    

    如果[ ]内没有其它字符 ,只有[^],就表示匹配一切字符,包括换行符,相比之下,点字符是不能匹配换行符的.

    另外 脱字符(^)只有在字符类的第一个位置才有特殊含义,否则就是字面含义.

    (2)连字符(-)

    某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。比如,[abc]可以写成[a-c][0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。

    /a-z/.test('b') // false
    /[a-z]/.test('b') // true
    

    上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。只有当连字号用在方括号之中,才表示连续的字符序列。

  5. 预定义模式

    指的是某些常见模式的简写方式.

    • \d 匹配0-9之间的任一数字 相当于[0-9]
    • \D 匹配所有0-9以外的字符 相当于[ ^0-9]
    • \w 匹配任意的字母/数字和下划线,相当于 [A-Za-z0-9_]
    • \W 匹配除了字母数字下划线以外的字符 相当于[ ^A-Za-z0-9_]
    • \s 匹配空格(包括换行符 制表符 空格符等),相当于[ \t\r\n\v\f]
    • \S 匹配非空格字符 相当于[ ^ \t\r\n\v\f]
    • \b 匹配词的边界
    • \B 匹配词的非边界,即在词的内部
  6. 重复类

    模式的精确匹配次数,使用大括号{}表示 ,{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示不少于n次,不多于m次.

    /lo{2}k/.test('look') //true
    /lo{2,5}k/.test('looook') //true
    
  7. 量词符

    量词符用来设定某个模式出现的次数,是重复类的简写

    • ? 表示某个模式出现0次或1次 {0,1}

    • * 表示某个模式出现0次或多次 {0,}

    • + 表示某个模式出现1次或多次 {1,}

      // t 出现0次或1次
      /t?est/.test('test') // true
      /t?est/.test('est') // true
      
      // t 出现1次或多次
      /t+est/.test('test') // true
      /t+est/.test('ttest') // true
      /t+est/.test('est') // false
      
      // t 出现0次或多次
      /t*est/.test('test') // true
      /t*est/.test('ttest') // true
      /t*est/.test('tttest') // true
      /t*est/.test('est') // true
      
      
  8. 贪婪模式

    上面三个量词符默认情况下都是最大可能匹配,直到匹配到不能匹配为止,这称为贪婪模式.

    如果要将贪婪模式改为非贪婪模式,可以在量词符后加一个?

    var s = 'aaa';
    s.match(/a+?/) //['a']
    
    

    一旦条件满足,就不再往下匹配.

    除了非贪婪模式的+ 还有非贪婪模式的* 和非贪婪模式的?

    • +? 表示某个模式出现1次或者多次,匹配时采用非贪婪模式
    • *? 表示某个模式出现0次或多次 ,匹配时采用非贪婪模式
    • ?? 表示某个模式出现0次或1次,匹配时采用非贪婪模式
  9. 组匹配

    ( ) 表示分组匹配,括号中的模式可以用来匹配分组的内容

    /fred+/.test('fredd') //true
    /(fred)+/.test('fredfred') //true
    
    

    组匹配非常有用,下面是一个匹配网页标签的例子

    var tagName = /<([^>]+)>[^<]*<\/\1>/;
    tagName.exec("<b>bold</b>")[1]
    //b
    
    

    下面是捕获带有属性标签的代码

    var html='<b class="hello">Hello</b><i>world</i>';
    var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;
    var match = tag.exec(html);
    match[1] //b
    match[2] //class=hello
    match[3] // Hello
    
    match = tag.exec(html);
    match[1] //i
    match[2] //""
    match[3] //world
    
    

    非捕获组

    (?:x) 称为非捕获组,表示不返回该组匹配的内容,匹配结果不计入这个括号

    有一个场景 : 需要匹配foo 或者 foofoo,正则写成/(foo){1,2}/

    这样写会占用一个组匹配,此时就可以使用非捕获组,将正则改为 /(?:foo){1,2}/ 作用一样,但是不会单独输出括号中的内容

    下面是用来分解网址的正则表达式。

    // 正常匹配
    var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
    
    url.exec('http://google.com/');
    // ["http://google.com/", "http", "google.com", "/"]
    
    // 非捕获组匹配
    var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
    
    url.exec('http://google.com/');
    // ["http://google.com/", "google.com", "/"]
    
    

    上面的代码中,前一个正则表达式是正常匹配,第一个括号返回网络协议;后一个正则表达式是非捕获匹配,返回结果中不包括网络协议。

    (3)先行断言

    x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/\d+(?=%)/

    “先行断言”中,括号里的部分是不会返回的。

    var m = 'abc'.match(/b(?=c)/);
    m // ["b"]
    
    

    上面的代码使用了先行断言,bc前面所以被匹配,但是括号对应的c不会被返回。

    (4)先行否定断言

    x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/\d+(?!%)/

    /\d+(?!\.)/.exec('3.14')
    // ["14"]
    
    

    上面代码中,正则表达式指定,只有不在小数点前面的数字才会被匹配,因此返回的结果就是14

    “先行否定断言”中,括号里的部分是不会返回的。

    var m = 'abd'.match(/b(?!c)/);
    m // ['b']
    
    

    上面的代码使用了先行否定断言,b不在c前面所以被匹配,而且括号对应的d不会被返回。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值