Python中的正则表达式(四)
2020-05-14
作者:老齐
与本文相关的图书推荐:《跟老齐学Python:轻松入门》

《Python正则表达式》这个系列,已经完成了三篇,本文是第四篇,请继续阅读。
如果错过了前两篇,请关注微信公众号:老齐教室。
前面已经对Python中正则表达的基本内容做了比较完整的讲述,从本文开始,将进入高级应用部分。
分组和捕获
分组,就是将一个正则表达式分成若干个子表达式。分组包括两个操作:
- 分组:即利用前面已经介绍过的元字符,在圆括号中写出一个一个的正则表达式(子表达式)
- 捕获:有的分组,可以按照子表达式匹配字符串。
分组符号
通常,用( )表示一个分组,在其中写子表达式。
1 | >>> re.search('(bar)', 'foo bar baz') |
在这个示例中,(bar)是一个分组的正则表达式,即一个子表达式,但是,这里因为只有一组,所以与不分组的bar效果是一样。
一个分组作为一个单元
如果在一个分组的子表达式后面跟一个量词,那么就是把这个分组作为一个单元。
例如,(bar)+,意味着将字符串bar看做一个单元,即要匹配至少1个bar。
1 | >>> re.search('(bar)+', 'foo bar baz') |
下面用表格的方式,比较bar+和(bar)+的区别:
| 正则表达式 | 说明 | 举例 |
|---|---|---|
bar+ |
+作用在字符r,匹配的字符串要求在ba的后面可以有1个或更多个r |
'bar', 'barr', 'barrr' |
(bar)+ |
+作用在bar,匹配的字符串中药出现bar |
'bar', 'barbar', 'barbarbar' |
下面再看个复杂的示例。
1 | >>> re.search('(ba[rz]){2,4}(qux)?', 'bazbarbazqux') |
正则表达式(ba[rz]){2,4}(qux)?中,(ba[rz])是一个分组,表示要匹配bar或baz。(ba[rz]){2,4}则表示匹配的数量范围(2到4个),后面的(qux)?又将qux作为一个单元,匹配0个或1个。
在上述示例基础上,进一步理解:
1 | >>> re.search('(foo(bar)?)+(\d\d\d)?', 'foofoobar') |
下面用表格的方式,将上面示例中的几个表达式进行说明。
| 正则表达式 | 说明 |
|---|---|
foo(bar)? |
匹配foo后面跟着0个或1个bar |
(foo(bar)?)+ |
按照上面规则匹配的字符串出现1次或多次 |
\d\d\d |
匹配三个整数字符 |
(\d\d\d)? |
0个或1个符合上述规则的字符串 |
将上表中的组合在一起,就是(foo(bar)?)+(\d\d\d)?正则表达式。
捕获
分组的目的之一是搜索字符串,根据分组原则捕获相应部分。
在re模块中,有re.search(),可以返回搜索到的匹配对象,针对分组操作,此对象有.groups和.group两个方法。
m.groups()
m.groups()根据正则表达式,返回所有分组所捕获的字符串。
1 | >>> m = re.search('(\w+),(\w+),(\w+)', 'foo,quux,baz') |
在此示例中,正则表达式(\w+),(\w+),(\w+)包含三个组,每组都是要匹配至少1个字母、数字,即要从foo,quux,baz中得到三个字符串foo、quux、baz,不包含原字符串中的,。
1 | >>> m.groups() |
执行m.groups(),返回结果为一个元组,其中包括所捕获的三个字符串。
m.group(n)
m.groups()返回的元组,包含了所有捕获的内容。但在操作中,可能需要返回某个分组,此时使用m.group(n)方法实现。
1 | >>> m = re.search('(\w+),(\w+),(\w+)', 'foo,quux,baz') |
m.group(1)中的参数是1,表示捕获第一个分组的结果——注意,不是从0开始。如果参数为0,会是下面的结果:
1 | >>> m.group(0) |
m.group()中的参数,还可以传入多个,如下所示:
1 | >>> m.groups() |
此时,能够按照参数的顺序和数值得到多个指定分组捕获,特别注意观察m.group(3, 2, 1)的结果。
向后引用
“向后引用”这个术语的英文是“backference”,很多中文资料翻译为“反向引用”,在本文中,我使用“向后引用”这个术语,原因在于这个翻译比较直白地反应了相关的效果。
所谓“向后引用”就是将前面的分组所捕获的结果向后再复制n个,比如:(\w+), \1,第一个分组(\w+),后面的\1表示将前面的分组捕获的结果在后面再次依样捕获1个。
1 | >>> regex = r'(\w+),\1' |
在这个示例中,分组(\w+)已经捕获了字符串foo,在正则表达式中的\1表示向后引用前面的捕获结果,即可以继续在字符串中搜索,能够要再捕获一个foo。再如:
1 | >>> m = re.search(regex, 'qux,qux') |
如果搜索的字符串是foo,qux,由于捕获第一个foo之后,继续在字符串中搜索,无法得到foo了,所以,会搜索失败。
1 | >>> m = re.search(regex, 'foo,qux') |
(未完,待续)
参考资料:https://realpython.com/regex-python/
搜索技术问答的公众号:老齐教室
在公众号中回复:老齐,可查看所有文章、书籍、课程。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
关注微信公众号,读文章、听课程,提升技能