正则表达式笔记

元字符

表达式 说明
. 匹配除了换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\W 匹配非字母或数字或下划线或汉字
\d 匹配数字
\D 匹配非数字

例:

  1. 匹配有 abc 开头的字符串

    1
    2
    \babc
    ^abc
  2. 匹配 1 开头的手机号码

    1
    ^1\d\d\d\d\d\d\d\d\d\d$

非打印字符

表达式 说明
\cx 匹配由 x 指明的控制字符。例如,\cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Za-z 之一。否则,将 c 视为一个原义的'c' 字符。
\f 匹配一个换页符。等价于 \x0c\cL
\n 匹配一个换行符。等价于 \x0a\cJ
\r 匹配一个回车符。等价于 \x0d\cM
\s 匹配任何空白字符,包括空格、制表符、换页符等等。注意 Unicode 正则表达式会匹配全角空格符。
\S 匹配任何非空白字符。
\t 匹配一个制表符。等价于 \x09\cI
\v 匹配一个垂直制表符。等价于 \x0b\cK

定位符

表达式 说明
\b 匹配单词边界,即字与空格间的位置。
\B 非单词边界匹配。
^ 匹配字符串的开始
$ 匹配字符串的结束

例:

  1. 匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt

    1
    \Bapt

重复限定符

表达式 说明
* 重复 0 次或多次
+ 重复 1 次或多次
? 重复 0 次或 1 次
{n} 重复 n 次
{n,} 重复 n 次及以上
{n,m} 重复 n 次到 m 次

例:

  1. 匹配 1 开头的手机号码

    1
    ^1\d{10}$
  2. 匹配 14-18 位的银行卡号

    1
    ^\d{14,18}$
  3. 匹配 a 开头,0 个或多个 b 结尾的字符串

    1
    ^ab*$

分组

使用小括号 () 来做分组,也就是说小括号中的内容为一个整体。

例:

  1. 匹配字符串包括 0 个及以上的 ab 开头

    1
    ^(ab)*

中括号表达式

表达式 说明
[ ] 匹配 [ ] 内的所有字符
[^ ] 匹配除了 [^ ] 内的所有字符

例:

  1. [ ] 的使用

    image-20220212110941769
    image-20220212110941769
  2. [^ ] 的使用

    image-20220212111046023
    image-20220212111046023
  3. 匹配字母和数字

    1
    [a-zA-Z0-9]
  4. 匹配指定数字 135

    1
    [135]

转义

匹配字符串中包括了正则的关键字时,在需要转义的字符前加斜杠 \

例:

  1. 匹配字符串包括 0 个及以上的 (ab) 开头

    1
    ^(\(ab\))*

条件或

使用符号 | 来表示或,也叫做分支条件。

例:

  1. 匹配联通的号码

    1
    ^(130|131|132|155|156|185|186|145|176)\d{8}$

零宽断言

  1. 正向先行断言

    匹配 pattern 前面的内容,不返回本身。

    1
    (?=pattern)

    例:

    匹配 123abc123defabc 前的 123

    1
    123(?=abc)
  2. 正向后行断言

    匹配 pattern 后面的内容,不返回本身。

    1
    (?<=pattern)

    例:

    匹配 123abc123defabc 后的 123

    1
    (?<=abc)123
  3. 负向先行断言

    匹配非 pattern 前面的内容,不返回本身。

    1
    (?=pattern)

    例:

    匹配 123abc123def 中不是 abc 前的 123

    1
    123(?!abc)
  4. 负向先行断言

    匹配非 pattern 后面的内容,不返回本身。

    1
    (?<!pattern)

    例:

    匹配 123abc123def 中不是 abc 后的 123

    1
    (?<!abc)123

捕获和非捕获

捕获组:匹配子表达式的内容,把匹配结果保存到内存中,以深度优先进行编号,之后可以通过序号或名称来使用这些匹配结果。

  1. 数字编号捕获组

    1
    (pattern)

    例:

    匹配固定电话 020-88888888

    1
    (0\d{2})-(\d{8})

    分组:

    编号 分组 内容
    0 (0\d{2})-(\d{8}) 020-88888888
    1 (0\d{2}) 020
    2 (\d{8}) 88888888
  2. 命名编号捕获组

    1
    (?<name>pattern)

    例:

    匹配固定电话 020-88888888

    1
    (?<quhao>0\d{2})-(?<haoma>\d{8})

    分组:

    名称 分组 内容
    0 (?<quhao>0\d{2})-(?<haoma>\d{8}) 020-88888888
    quhao (?<quhao>0\d{2}) 020
    haoma (?<haoma>\d{8}) 88888888
  3. 非捕获组

    1
    (?:pattern)

    例:

    匹配固定电话 020-88888888

    1
    (?:0\d{2})-(\d{8})

    分组:

    编号 分组 内容
    0 (?:0\d{2})-(\d{8}) 020-88888888
    1 (\d{8}) 88888888

反向引用

引用捕获内容

  1. 数字编号组反向引用:

    1
    2
    3
    \k<number>
    # or
    \number
  2. 命名编号组反向引用:

    1
    2
    3
    \k<name>
    # or
    \'name'

    例:

    匹配两个重复字符:

    1
    2
    3
    (\w)\1
    # or
    (?<char>\w)\k<char>

贪婪与非贪婪

贪婪

特性:一次性读入整个字符串进行匹配,每当不匹配就舍弃最右边一个字符,继续匹配,依次匹配和舍弃(这种匹配 - 舍奔的方式也叫做回湖),直到匹配成功或者把整个字符串舍弃完为止,因此它是一种最大化的数据返回能多不会少。

重复限定符就是贪婪量词,如:

1
\d{3,6}

假如字符串有 6 个数字可以匹配,就全部匹配。

多个贪婪在一起时,如果字符串能满足他们各自最大成都的匹配时,就互不干扰,否则会根据深度优先原则,也就是从左到右的每一个贪婪量词,最大数量的满足,剩余再分配下一个量词匹配。

非贪婪

特性:从左到右,从字符串的最左边开始匹配,每次试图不读入字符匹配,匹配成功,则完成匹配,否则读入一个字符再匹配,依此循环(读入字符、匹配)直到匹配成功或者把字符串的字符匹配完为止。

非贪婪量词实在贪婪量词后加 ?

表达式 说明
*? 重复 0 次或多次,懒惰
+? 重复 1 次或多次,懒惰
?? 重复 0 次或 1 次,懒惰
{n,}? 重复 n 次及以上,懒惰
{n,m}? 重复 n 次到 m 次,懒惰

参考

https://www.runoob.com/regexp/regexp-syntax.html

https://www.bilibili.com/video/BV1K341187wW