Python 正则表达式
1 简介
2 模块和对象
为了更好的理解 re
模块的使用, 我们首先将 re
模块涉及到的 三个对象 列举出来:
- 模块对象: 模块对象指的就是
re
模块本身。 - 正则表达式对象: 通常为调用
re.compile
编译正则表达式模式后返回的对象。 - 正则表达式匹配对象: 通常为调用
re.match
或re.search
后返回的对象。
将 三个对象 列举出来的原因是需要 分清楚 我们调用的 方法 或 函数 到底是属于那一个对象。
我就在错误的对象身上调用过的正确的方法并得到了合适一个异常。
首先, 模块对象 和 正则表达式对象 的方法基本相同, 一定程度上, 模块对象 的是对 正则表达式对象 的一层封装。
然后, 正则表达式匹配对象 的对象和另外两者的区别很大, 使用的时候需要分清楚。
3 模块对象和正则表达式对象
由于 模块对象 和 正则表达式 对象的使用十分接近, 就把两者的内容放在一起了。
- re.compile(pattern, flags=0)
这个方法只适用于 模块对象, 使用任何可选的
flag
来编译正则表达式模式,并返回一个 正则表达式对象.多个标记可以通过按位或操作符
|
合并.详细的
flags
可以参考官方文档: Module Contents- match(pattern, string, flags=0)
尝试从字符串的 起始部分 对模式进行匹配, 如果匹配成功就返回一个 匹配对象, 匹配失败返回
None
.注意: 是从起始部分进行匹配。
- search(pattern, string, flags=0)
这个方法的工作方式和
match
基本相同, 不同之处在于search
会在字符串的 任意位置 尝试对模式进行匹配。 匹配成功返回 匹配对象, 匹配失败返回None
.注意: 是任意位置进行匹配。
- findall(pattern, string, [,flags])
这个方法查找字符串中 所有 非重复出现的正则表达式模式, 并返回一个列表。 如果没有匹配到的话就返回一个 空的 列表。
需要注意的一种情况是匹配模式的 分组多于 1 的时候的匹配结果:
In [2]: re.findall(r'\w+', 're: Regular expression operations') Out[2]: ['re', 'Regular', 'expression', 'operations'] In [3]: re.findall(r'(\w+)', 're: Regular expression operations') Out[3]: ['re', 'Regular', 'expression', 'operations'] In [5]: re.findall(r'(\w+).(\w+)', 're: Regular expression operations') Out[5]: [('Regular', 'expression'), ('operatio', 's')]
上面三个语句分别对应分组为
0
,1
,2
时的执行情况.分组为
0
或1
时, 返回的 列表 中的元素都是匹配的 字符串.当分组为
2
时, 返回的 列表 中的元素就变为了 元组.元组 内的元素的顺序对应每个 组 的匹配结果。
In [6]: re.findall(r'(\w+(\w))', 're: Regular expression operations') Out[6]: [('re', 'e'), ('Regular', 'r'), ('expression', 'n'), ('operations', 's')]
对于匹配模式
(\w+(\w))
来说,(\w+(\w))
是分组1
, 而(\w)
是分组2
.- finditer(pattern, string, [,flags])
- 与
findall
相同, 只不过返回的是一个 迭代器, 而不是 列表. - split(pattern, string, max=0)
参考
sstr.split
, 作用是类似的。 只不过分割字符串的参考依据由单个字符变为了 匹配模式.可以通过
max
指定最大分割次数:In [13]: re.split(r'\w\s\w', 'Hello World !') Out[13]: ['Hell', 'orld !']
- sub(pattern, repl, string, count=0)
使用
repl
替换string
中出现的和pattern
相匹配的字符串, 通过count
指定替换次数, 默认为替换所有。注:
repl
中可以使用 回溯引用.In [18]: re.sub(r'\w+?(T)\w', r'\1', 'asdTgdfTdgfhTdsfgTf') Out[18]: 'TTTT'
PS: 如无特殊说明, 那么该方法同时适用于 模块对象 和 正则表达式对象.
4 正则表达式匹配对象
匹配对象 通常为 re.match
或 re.search
返回的对象。
在涉及 匹配对象 的方法之前, 需要了解的一个东西是 正则表达式的分组.
通常, 我们可以在 匹配模式 中使用 ()
来定义 元组(子组). 这些 元组 会根据定义的顺序被设置一个 编号.
这个 编号 被用来代表那个 分组, 正则表达式中的 回溯引用 等也会用到那个编号。
首先, 最基本的一点是: 整个匹配模式的编号是 0
.
对于剩下的分组, 可以通过网站 JavaScript Regular Expression Visualizer. 进行可视化分析.
虽然是 JavaScript
的正则表达式, 但是道理是通的.
比如: ^(\w+)\s+(\w{3}(\w{2}))+$
的分组可以表示为:
明白了分组的概念, 再来理解 匹配对象 的方法就容易很多了:
- group(num=0)
- 返回整个匹配对象或编号为
num
的特定子组 - groups(default=None)
- 返回一个包含所有匹配子组的元组
- groupdict(default=None)
- 返回一个包含所有匹配的 命名子组 (Python 语法扩展) 的字典,所有的子组名作为字典的键。
需要注意的是, 如果 re.match
或 re.search
的匹配不成功, 那么返回的结果就是 None
,
而不是 匹配对象.
5 语法扩展和原始字符串
Python
对正则表达式的语法做了一些扩展:
扩展表示法 | 作用 | 例子 |
---|---|---|
(?iLmsux) |
放在匹配模式的 开头, 相当于 flags 参数 |
(?i)\w+ 不区分大小写 |
(?:...) |
表示一个匹配 不用保存 的分组 | (?:\w+) |
(?P<name>...) |
定义一个 命名分组 | (?P<word>\w+) |
(?P=name) |
命名分组的 回溯引用 | (P=word) |
(?#...) |
注释 | (?#comment) |
适当程度上的使用 扩展语法 可以节约一定的工作量。
原始字符串:
在正则表达式中, \
是转义字符。
在 Python
中, \
也是转义字符。
这时, 如果不使用原始字符串, 那么匹配模式中的 \
就需要写为 \\
.
如果要匹配 \
, 那么匹配模式就成了 \\\\
.
这样十分影响匹配模式的阅读理解, 还容易出错。
此时, 使用原始字符串解决这一问题:
r'string' # 在字符串前面加上 r 即可