2. Python 正则

import re

Python 的 re 模块提供了与 Perl 语言类似的正则表达式匹配操作。

模式(Pattern)和被搜索的字符串既可以是 Unicode 字符串( str ),也可以是 8 位字节串( bytes ),但是两者不能混用。

模式通常都使用原始字符串表示法:在带有 r 前缀的字符串字面值中,反斜杠不必做任何特殊处理。

2.1. 正则标志

  • re.I :忽略大小写。

  • re.M :多行模式, ^ 匹配字符串的开始,以及每一行的开始(换行符后面紧跟的符号); $ 匹配字符串尾,以及每一行的结尾(换行符前面那个符号)。

  • re.S. 匹配任何字符,包括换行符。

  • re.X :为了增加可读性,忽略空格和 # 后面的注释。下面两个正则表达式等价:

    a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
    b = re.compile(r"\d+\.\d*")
    

2.2. re.compile

re.compile(pattern, flags=0)

将正则表达式的样式编译为一个正则表达式对象(正则对象)Pattern。 flag 是正则标志。

正则表达式对象 Pattern 支持以下方法和属性:

Pattern.search(string[, pos[, endpos]])

扫描整个 string 寻找第一个匹配的位置,并返回一个相应的匹配对象;如果没有匹配,就返回 None

Pattern.match(string[, pos[, endpos]])

如果 string 的开始位置能够找到这个正则样式的任意个匹配,就返回一个相应的匹配对象;如果不匹配,就返回 None

Pattern.fullmatch(string[, pos[, endpos]])

如果整个 string 匹配这个正则表达式,就返回一个相应的匹配对象,否则就返回 None

Pattern.split(string, maxsplit=0)

等价于 re.split

Pattern.findall(string[, pos[, endpos]])

类似于 re.findall ,也可以接收可选参数 pos 和 endpos ,限制搜索范围。

Pattern.sub(repl, string, count=0)

等价于 re.sub

Pattern.groups()

捕获到的模式串中组的数量。

2.4. re.match

re.match(pattern, string, flags=0)

如果 string 开始的 0 或者多个字符匹配到了正则表达式样式,就返回一个相应的匹配对象;如果没有匹配,就返回 None

1>>> re.match("c", "abcdef") # No match
2>>> re.search("c", "abcdef") # match
3<re.Match object; span=(2, 3), match='c'>
4>>> re.search("^c", "abcdef") # No match
5>>> re.search("^a", "abcdef") # match
6<re.Match object; span=(0, 1), match='a'>

2.5. 匹配对象

匹配对象 Match 常用成员方法如下:

Match.groups(default=None)

返回一个元组,包含所有匹配的子组。

Match.groupdict(default=None)

返回匹配子组的字典形式,需要配合 ?P<first_name> 使用。

1>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
2>>> m.groupdict()
3{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
4>>> m.group('first_name')
5'Malcolm'
Match.group([group1, ...])

返回一个或者多个匹配的子组。如果只有一个参数,结果就是一个字符串;如果有多个参数,结果就是一个元组(每个参数对应一个项);如果没有参数,或者参数是 0,返回所有的匹配。

1>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
2>>> m.group(0)       # The entire match
3'Isaac Newton'
4>>> m.group(1)       # The first parenthesized subgroup.
5'Isaac'
6>>> m.group(2)       # The second parenthesized subgroup.
7'Newton'
8>>> m.group(1, 2)    # Multiple arguments give us a tuple.
9('Isaac', 'Newton')
Match.start([group])

返回 group 匹配到的字串的开始位置。group 默认为 0(意思是整个匹配的子串)。

Match.end([group])

返回 group 匹配到的字串的结束位置(前闭后开)。group 默认为 0(意思是整个匹配的子串)。

Match.span([group])

对于一个匹配 m , 返回一个二元组 (m.start(group), m.end(group)) 。 注意如果 group 没有在这个匹配中,就返回 (-1, -1) 。group 默认为 0,就是整个匹配。

2.6. re.findall

re.findall(pattern, string, flags=0)

返回 pattern 在 string 中的所有非重叠(Non-overlapping )匹配,以字符串列表或字符串元组列表的形式。对 string 的扫描从左至右,匹配结果按照找到的顺序返回。 空匹配也包括在结果中。

返回结果取决于模式中捕获组的数量。如果没有组,返回与整个模式匹配的字符串列表。如果有且仅有一个组,返回与该组匹配的字符串列表。如果有多个组,返回与这些组匹配的字符串元组列表。 非捕获组不影响结果。

1>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
2['foot', 'fell', 'fastest']
3>>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
4[('width', '20'), ('height', '10')]

迭代器版本: re.finditer(pattern, string, flags=0)

2.7. re.split

re.split(pattern, string, maxsplit=0, flags=0)

用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的字符也会包含在列表里。 如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。 如果没有匹配,不会进行分割。

1>>> re.split(r'\W+', 'Words, words, hello.') ## 注意:是大写的 W
2['Words', 'words', 'hello', '']
3>>> re.split(r'(\W+)', 'Words, words, hello.')
4['Words', ', ', 'words', ', ', 'hello', '.', '']

2.8. re.sub

re.sub(pattern, repl, string, count=0, flags=0)

返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。 如果 pattern 没有找到,则直接返回 string。

repl 可以是字符串或函数,这个函数只能有一个匹配对象参数,并返回一个替换后的字符串。

可选参数 count 是要替换的最大次数,必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换。

>>> re.sub(r'\D', '', '1234-5678-9999')
'123456789999'

2.9. 参考资料

  1. Python 正则表达式

  1. re 正则表达式操作