前言

正则表达式是特殊的字符串序列,可以实现模糊匹配一个字符串是否符合某种指定模式。

用法

语法

精确字符匹配

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符
[…] 匹配一组字符,或的关系,如[amk] 匹配 ‘a’,’m’或’k’
[^…] 匹配不在[]中的字符,非的关系,如[^abc] 匹配除了a,b,c之外的字符。
\w 匹配字母数字及下划线
\W 匹配非字母数字及下划线
\s 匹配任意空白字符,等价于 **[ \t\n\r\f]**。
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t, 等. 匹配一个换行符。匹配一个制表符。等

变长字符匹配

将上方精确字符模式与以下模式字符组合,可以匹配变长字符

  • *表示任意个字符(包括0个),(如:\s*表示匹配任意多个空白字符,以下以此类推)
  • +表示至少一个字符
  • ?表示0个或1个字符
  • {n}表示n个字符
  • {n,m}表示n-m个字符

界定符

当需要以某些开头/结尾特征作为模式来匹配,而匹配结果中又需要/不需要保留开头/结尾时,采用定界符。

举例: s =”Labcdef;”

  • 不包含匹配的开头和结尾:(?<=L).*?(?=;) 【结果:abcdef】
  • 不包含开头,包含结尾:(?<=L).*?(?<=;) 【结果:abcdef;】
  • 包含开头,不包含结尾:’(?=L).*?(?=;) 【结果:Labcdef】

非惰性匹配

  • 正则表达式默认是惰性匹配(或叫贪婪匹配),即匹配尽可能长的字符串
  • 非惰性匹配:+或*后跟?即表示非惰性匹配,匹配尽可能短的字符串
  • 注意:一个?只保证所跟的+或*所在字符是非惰性匹配,举例如下:
1
2
3
4
5
6
7
8
9
10
>>> import re
>>> s = "Lab>c;d>;"

>>> re_key = re.compile(r'L.*>.*?;')
>>> re_key.findall(s)
['Lab>c;d>;']

>>> re_key_1 = re.compile(r'L.*?>.*?;')
>>> re_key_1.findall(s)
['Lab>c;']

常见用法

  • 匹配字符串

    • 语法:findall(string,start_pos,end_pos)
      • string:正则表达式
      • start_pos:可选参数,指定字符串的搜索起始位置,默认为 0
      • end_pos字符串的搜索结束位置,默认为字符串长度
    • 举例:
    1
    2
    3
    4
    5
    6
    7
    8
    import re

    # 使用re.compile预编译正则表达式,使用r前缀就不用考虑对正则表达式中的\转义
    re_key = re.compile(r'正则表达式')

    # findall匹配所有满足的字符串,以列表形式返回
    res = re_key.findall(待搜索字符串)

  • 分组提取子串

    • 语法:在正则表达式中使用 () 定义要提取的分组,在Match对象上用group()方法提取子串
    • 举例:(来自廖雪峰网站)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
    >>> m
    <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
    >>> m.group(0)
    '010-12345' # group(0)永远是与整个正则表达式相匹配的字符串
    >>> m.group(1)
    '010'
    >>> m.group(2)
    '12345'
  • 替换字符串(可用于删除)

    • 语法:re.sub(正则表达式, 替换的字符串, 要被查找的原始字符串, count=0, flags=0)
      • count:替换次数,默认 替换所有的匹配
    • 举例:(来自菜鸟教程)
    1
    2
    3
    4
    5
    6
    7
    8
    phone = "2004-959-559 # 这是一个国外电话号码"

    # 删除字符串中的 Python注释
    num = re.sub(r'#.*$', "", phone) # num = 2004-959-559

    # 删除非数字(-)的字符串
    num = re.sub(r'\D', "", phone) # num = 2004959559 # 这是一个国外电话号码

  • 切分字符串(string.split()只能使用固定字符串分割,re.split()更灵活)

    • 语法:re.split(正则表达式,待切分字符串)
    • 举例:
    1
    2
    3
    4
    5
    s = 'a b   c'

    # 分隔所有字符
    print(s.split(' ')) # ['a', 'b', '', '', 'c']
    re.split(r'\s+', s) # ['a', 'b', 'c']

用途

  • 可以将搜索范围拼接成一个字符串整体,采用正则匹配快速获得需要的结果。

参考文章