正则表达式

作者: snow_in | 来源:发表于2018-07-07 20:30 被阅读13次
    元字符:在正则表达式中有特殊语义的字符
    常用元字符 含义
    . 匹配除换行符以外的任何字符
    \w 匹配字母、数字、下划线
    \W 匹配不是字母、数字、下划线的字符
    \d 匹配数字, 相当于[0-9]
    \D 匹配不是数字的字符
    \s 匹配任何不可见字符,包括空格、制表符、换行符等
    \S 匹配任意可见字符
    \b 匹配一个词的边界。一个词的边界就是没有其他“字”字符在其前面或后面的位置
    \B 匹配不是词的边界
    ^ 匹配字符串的开始位置
    $ 匹配字符串的结束位置

    这里的\w和\W以及\d和\D等都是互斥等,组合起来就是字符等全集,但跟 . 不相等,因为 . 不包括换行符。

    字符集:使用[] 括起字符串来创建字符集,可以匹配[]里面的任意字符

    一些特殊符号在字符集中是没有特殊语义的,不需要用转义符转义,例如:
    [.*+?^=!:${}()|[]/\],但如果不在字符集中是需要转义的,比如 /./表示匹配除换行符之外的任何字符 , 如果想匹配 . 字符本身,就需要:/\./.
    一些元字符也可以用字符集来表示,比如:\d == [0-9] \w == [0-9A-Za-z_].
    '-' 短横线在字符集中表示区间,如果只有 ‘-’ 一个字符,就可以匹配'-' 不需要转义
    /[-]/.test('-'); // true
    /[-a]/.test('-') // true
    /[a-]/.test('-') // true

    分支: 其实就是表示或的概念

    (aa|ba|ca): 匹配aa, ba或ca,这个也可以用字符集表示:/[abc]a/, 这种特殊情况可以这样表示,但是像(aa|bb|cc)这种就不可以了

    量词:表示字符重复次数
    常用元字符 含义
    * 重复任意次,相当于{0,}
    ? 重复0次或1次,相当于{0,1}
    + 重复一次或更多次,相当于{1,}
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
    分组和引用

    分组:使用()将字符作为一个最小单元,并且可以记住匹配项
    引用:可以使用反斜杠‘\’来引用分组的表达式,从最外层的括号开始计算分组,依次为分组一、分组二...

    分组1.png

    上面图片已经确定了分组,接下来我们就可以使用引用了
    /(\d{4})-(\d{2})-\2/:\2 就表示引用 (\d{2}) 的内容,和 (\d{2}) 的内容相同
    /(\d{4})-(\d{2})-\2/.test('2018-07-07') // true
    /(\d{4})-(\d{2})-\2/.test('2018-07-09') // false

    \1, \2, \n 这种是用在正则表达式的匹配环节,但是这种123的记法不方便,你还得一个个去数。有一种给分组命名的方法可以方便记忆: ?<name>,访问捕获的组可以使用 \k<name>。在正则表达式的替换环节,则要使用像 $1、$2...$9 这样的语法,$& 可以匹配全部内容,而不只是分组内容。

    命名.png

    groups字段中展示了各个捕获组的内容。

    /(?<year>\d{4})-(?<month>\d{2})-\k<month>/.test('2018-08-08') // true

    零宽断言:匹配到的内容不保存到匹配结果中去

    作用是给指定位置添加一个限定条件,用来规定此位置之前或者之后的字符必须满足限定条件才能使正则中的子表达式匹配成功。

    1. 根据方向到不同,分为lookahead(向前查找)和lookbehind(向后查找)
    2. 根据判定原则,分为 肯定和否定
    从左到右/pattern的前面位置 从右到左/pattern的后面位置
    肯定/正 (?=pattern)(子字符串前面有pattern才会匹配) (?<=pattern) (子字符串后面有pattern才会匹配)
    否定/负 (?!pattern)(子字符串前面没有pattern才会匹配) (?<!pattern) (子字符串后面没有pattern才会匹配)

    向后看是有个<,肯定=, 否定!

    惰性&贪婪

    贪婪模式:在匹配成功的情况下,尽可能多的去匹配

    比如:/.*bbb/g.test(‘abbbaabbbaaabbb1234')
    *会先尽可能多的匹配,这里就是匹配全部字符串,然后再查找b,如果不符合条件就向前回溯,匹配'abbbaabbbaaabbb123', 再向后查找b,不满足继续回溯...


    贪婪一.png
    贪婪二.png 贪婪三.png

    惰性模式:在匹配成功的情况下,尽可能少的去匹配

    比如:/.*?bbb/g.test(‘abbbaabbbaaabbb1234’)
    *会尽量少的匹配,第一次会匹配0次,然后向后查找b


    惰性1.png 惰性儿.png 惰性三.png

    到底是使用贪婪模式还是惰性模式要看自己对所要匹配对字符串的熟悉程度,对字符串的特性越熟悉,越容易判定使用哪种模式,自然也能提升性能。
    贪婪要不停的回溯,惰性则是从前往后匹配

    修饰符
    修饰符 含义
    i ignoreCase(忽略大小写)
    g global(全局)
    m multiline(多行)
    s dotAll(. 能匹配所有字符)
    y sticky(粘连)

    m表示匹配多行,主要是表达式加^时会有差别,每次都从每一行的开头匹配
    '1\n2'.match(/^\d/g) // ["1"]
    '1\n2'.match(/^\d/mg) // ["1", "2"] 注意要加上g,匹配全局,不然结果也只是 1

    s: . 表示除换行之外的所有字符,加上s修饰符就可以表示所有字符
    /./.test('\n') // false
    /./s.test('\n') // true

    使用方法
    方法 描述
    exec 在字符串中执行查找匹配,返回一个数组(没匹配到返回null)
    test 测试字符串是否匹配,返回true或false
    match 在字符串中执行查找匹配的String方法,返回数组或null
    search 在字符串中测试匹配的String方法,返回匹配到的位置索引或-1
    replace 在字符串中执行查找匹配的String方法,并用替换字符串替换掉匹配到的字符串
    split 使用正则表达式或字符串分割字符串,并将分割后的结果存储到数组中的String方法

    match和exec的区别除了一个是String方法一个是RegExp方法,还有就是有g修饰符时候的表现

    1. 无子表达式
      'abbbaabbbaaabbb1234'.match(/ab/g) // ["abbb", "a", "abbb", "a", "a", "abbb"]
      /ab
      /g.exec('abbbaabbbaaabbb1234') // ["abbb", index: 0, input: "abbbaabbbaaabbb1234", groups: undefined] (返回第一个匹配的字符串内容)
    2. 有子表达式
      'abbbaabbbaaabbb1234'.match(/a(a)/g) // ["a", "aa", "aaa"] (忽略子表达式,只查找全匹配正则表达式并返回所有内容)
      /a(a
      )/g.exec('abbbaabbbaaabbb1234') // ["a", "", index: 0, input: "abbbaabbbaaabbb1234", groups: undefined]

    相关文章

      网友评论

        本文标题:正则表达式

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