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/
搜索技术问答的公众号:老齐教室
在公众号中回复:老齐,可查看所有文章、书籍、课程。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
关注微信公众号,读文章、听课程,提升技能