0%

正则表达式

正则表达式是经过专门编写的文本字符串,用来匹配字符串集合中符合该模式的所有字符串。

元字符

在正则表达式中,元字符有特殊的含义。正则表达式的元字符如下。如果需要匹配元字符,需要通过\转义。或者将元字符放在\Q\E的中间,例如\Q^$\E匹配字符串^$

元字符 名称 作用
. 句点 匹配任意字符
^ 脱字符 行起始锚位符
$ 美元符 行结束锚位符
* 星号 匹配零次或多次的量词
+ 加号 匹配一次或多次的量词
? 问号 匹配零次或一次的量词
| 竖线符 选择操作(或)
( 左括号 分组起始
) 右括号 分组结束
{ 左花括号 量词或代码块起始
} 右花括号 量词或代码块结束
[ 左方括号 字符组起始
] 右方括号 字符组结束
\ 反斜线 对字符转义

字符组

关键点:

  • []表示字符组
  • 字符中间的-表示范围
    • 注意[0-9][-09]的区别
  • 开头的^表示取反
  • 字符组一定会消耗一个字符
  • 字符组内部的元字符与字符组外部的元字符完全不一样
    • 开头的-和字符中间的-有特殊含义,其余字符均匹配自身
示例 说明
[12] 匹配字符1或2。
[^12] 不匹配字符1和2
[0-9] 匹配数字字符
[a-z] 匹配小写字母

常用字符组缩写

字符组缩写 字符组 说明
\d [0-9] 数字字符
\D [^0-9] 非数字字符
\s [ \t\n\r] 空白符
\S [^ \t\n\r] 非空白符
\w [_a-zA-Z0-9] 单词字符
\W [^_a-zA-Z0-9] 非单词字符
. [^\n\r] 除行结束符之外的所有字符

POSIX字符组

字符组 描述
[[:alnum:]] 匹配字母及数字
[[:alpha:]] 匹配字母
[[:ascii:]] 匹配ASCII 字符(共128 个)
[[:blank:]] 匹配空白字符
[[:ctrl:]] 匹配控制字符
[[:digit:]] 匹配数字
[[:graph:]] 匹配图形字符
[[:lower:]] 匹配小写字母
[[:print:]] 匹配可打印字符
[[:punct:]] 匹配标点符号
[[:space:]] 匹配空格字符
[[:upper:]] 匹配大写字母
[[:word:]] 匹配单词字符
[[:xdigit:]] 匹配十六进制数字

捕获分组与后向引用

使用()对正则表达式匹配的字符进行分组,分组不会改变正则表达式的匹配。使用\1$1对分组进行引用。\1表示第一个开括号(的分组,\2表示第二个开括号的分组。

例如正则表达式(\d)\d\1匹配字符串575。第一个\d匹配字符5并加入分组,\1对分组进行引用。

(?:)表示分组但是不引用,这会提高正则表达式的性能。

量词

例如正则表达式:a?。量词?修饰前面的a,表示字符a出现0次或1次。量词也可以用{min,max}表达。

量词 说明
? 0或1次,{0,1}
+ 1或无穷次,{1,}
* 0或无穷次,{0,}
{n} n次
{n,m} 最少n次,最多m次
{n,} 最少n次

量词默认使用贪心原则,即尽可能匹配更多的内容。量词首先尝试匹配整个字符串,如果失败则回退一个字符后再次尝试。

懒惰是另一种策略,它从目标的起始位置开始尝试寻找匹配,每次检查字符串的一个字符,寻找它要匹配的内容。最后,它会尝试匹配整个字符串。要使用懒惰量词,需要在普通量词后添加?

占有量词会覆盖整个目标然后尝试寻找匹配内容,但只尝试一次,不会回溯。需要在普通量词后添加+

选择

竖线符|表示选择,从多个表达式中选择一个匹配。例如a|ab表示匹配字符a或字符串ab。注意选择和字符数组的区别,字符数组一次只能匹配一个字符,选择根据情况可以匹配多个字符。

可以借助分组,为选择确定一个明确的边界。例如表达式a|bcd(a|bc)d的区别。

锚位符

锚位符用来匹配位置,不消耗任何字符。

锚位符 说明
^ 行起始位置
$ 行结束位置
\b 单词边界
\B 非单词边界
\< 单词开头。旧语法,可能不支持
\> 单词结尾。旧语法,可能不支持
\A 主题词的开始
\Z 主题词的结尾

环视

环视是一种非捕获分组,根据某个模式之前或之后的内容匹配其他模式。环视不匹配任何字符,只匹配文本中的特定位置。环视不会占用字符。

环视 正则表达式 说明
肯定顺序环视 (?=…) 子表达式够匹配右侧文本
否定顺序环视 (?!..) 子表达式不能匹配右侧文本
肯定逆序环视 (?<=…) 子表达式够匹配左侧文本
否定逆序环视 (?<!..) 子表达式不能够匹配左侧文本

考虑字符串see Jeffs book,正则表达式(?=s\b)匹配fs中间的位置,因为这个位置右侧包含字符串s\b

考虑任意一个位置,如果对右边的字符有要求,可以使用肯定顺序环视(枚举)或否定逆序环视(排除)。

1
2
(?=s\b)   # 只能匹配 f 和 s 中间的位置
(?<!s\b) # 空格和 b 中间的位置不能匹配,其余位置均可以匹配。f 和 s 中间的位置也能匹配。

如果对左边的字符有要求,可以使用肯定逆序环视(枚举)或否定顺序环视(排除)。

学习资料

Python使用正则表达式

参考:https://docs.python.org/zh-cn/3/library/re.html

1
2
3
4
5
6
7
8
import re
reg_expre = re.compile('(?P<key1>\d{3})-?(?P<key2>\d{4})')
m = reg_expre.match("123-4567")
if m:
print(m.groupdict()) # ('123', '4567')
print(m.groups()) # {'key1': '123', 'key2': '4567'}
print(m.group(1)) # '123'
print(m.group('key2')) # '4567'