您的位置 首页 > 腾讯云社区

Python中的正则表达式(四)---用户7315084

《Python正则表达式》这个系列,已经完成了三篇,本文是第四篇,请继续阅读。

如果错过了前两篇,请关注微信公众号:老齐教室。

前面已经对Python中正则表达的基本内容做了比较完整的讲述,从本文开始,将进入高级应用部分。

分组和捕获

分组,就是将一个正则表达式分成若干个子表达式。分组包括两个操作:

分组:即利用前面已经介绍过的元字符,在圆括号中写出一个一个的正则表达式(子表达式)捕获:有的分组,可以按照子表达式匹配字符串。分组符号

通常,用( )表示一个分组,在其中写子表达式。

>>> re.search('(bar)', 'foo bar baz') <_sre.SRE_Match object; span=(4, 7), match='bar'> >>> re.search('bar', 'foo bar baz') <_sre.SRE_Match object; span=(4, 7), match='bar'>

在这个示例中,(bar)是一个分组的正则表达式,即一个子表达式,但是,这里因为只有一组,所以与不分组的bar效果是一样。

一个分组作为一个单元

如果在一个分组的子表达式后面跟一个量词,那么就是把这个分组作为一个单元。

例如,(bar)+,意味着将字符串bar看做一个单元,即要匹配至少1个bar。

>>> re.search('(bar)+', 'foo bar baz') <_sre.SRE_Match object; span=(4, 7), match='bar'> >>> re.search('(bar)+', 'foo barbar baz') <_sre.SRE_Match object; span=(4, 10), match='barbar'> >>> re.search('(bar)+', 'foo barbarbarbar baz') <_sre.SRE_Match object; span=(4, 16), match='barbarbarbar'>

下面用表格的方式,比较bar+和(bar)+的区别:

正则表达式

说明

举例

bar+

+作用在字符r,匹配的字符串要求在ba的后面可以有1个或更多个r

'bar', 'barr', 'barrr'

(bar)+

+作用在bar,匹配的字符串中药出现bar

'bar', 'barbar', 'barbarbar'

下面再看个复杂的示例。

>>> re.search('(ba[rz]){2,4}(qux)?', 'bazbarbazqux') <_sre.SRE_Match object; span=(0, 12), match='bazbarbazqux'> >>> re.search('(ba[rz]){2,4}(qux)?', 'barbar') <_sre.SRE_Match object; span=(0, 6), match='barbar'>

正则表达式(ba[rz]){2,4}(qux)?中,(ba[rz])是一个分组,表示要匹配bar或baz。(ba[rz]){2,4}则表示匹配的数量范围(2到4个),后面的(qux)?又将qux作为一个单元,匹配0个或1个。

在上述示例基础上,进一步理解:

>>> re.search('(foo(bar)?)+(ddd)?', 'foofoobar') <_sre.SRE_Match object; span=(0, 9), match='foofoobar'> >>> re.search('(foo(bar)?)+(ddd)?', 'foofoobar123') <_sre.SRE_Match object; span=(0, 12), match='foofoobar123'> >>> re.search('(foo(bar)?)+(ddd)?', 'foofoo123') <_sre.SRE_Match object; span=(0, 9), match='foofoo123'>

下面用表格的方式,将上面示例中的几个表达式进行说明。

匹配foo后面跟着0个或1个bar

将上表中的组合在一起,就是(foo(bar)?)+(ddd)?正则表达式。

捕获

分组的目的之一是搜索字符串,根据分组原则捕获相应部分。

在re模块中,有re.search(),可以返回搜索到的匹配对象,针对分组操作,此对象有.groups和.group两个方法。

m.groups()

m.groups()根据正则表达式,返回所有分组所捕获的字符串。

>>> m = re.search('(w+),(w+),(w+)', 'foo,quux,baz') >>> m <_sre.SRE_Match object; span=(0, 12), match='foo:quux:baz'>

在此示例中,正则表达式(w+),(w+),(w+)包含三个组,每组都是要匹配至少1个字母、数字,即要从foo,quux,baz中得到三个字符串foo、quux、baz,不包含原字符串中的,。

>>> m.groups() ('foo', 'quux', 'baz')

执行m.groups(),返回结果为一个元组,其中包括所捕获的三个字符串。

m.group(n)

m.groups()返回的元组,包含了所有捕获的内容。但在操作中,可能需要返回某个分组,此时使用m.group(n)方法实现。

>>> m = re.search('(w+),(w+),(w+)', 'foo,quux,baz') >>> m.groups() ('foo', 'quux', 'baz') >>> m.group(1) 'foo' >>> m.group(2) 'quux' >>> m.group(3) 'baz'

m.group(1)中的参数是1,表示捕获第一个分组的结果——注意,不是从0开始。如果参数为0,会是下面的结果:

>>> m.group(0) 'foo,quux,baz' >>> m.group() # 不写参数,即默认参数是0 'foo,quux,baz'

m.group()中的参数,还可以传入多个,如下所示:

>>> m.groups() ('foo', 'quux', 'baz') >>> m.group(2, 3) ('quux', 'baz') >>> m.group(3, 2, 1) ('baz', 'quux', 'foo')

此时,能够按照参数的顺序和数值得到多个指定分组捕获,特别注意观察m.group(3, 2, 1)的结果。

向后引用

“向后引用”这个术语的英文是“backference”,很多中文资料翻译为“反向引用”,在本文中,我使用“向后引用”这个术语,原因在于这个翻译比较直白地反应了相关的效果。

所谓“向后引用”就是将前面的分组所捕获的结果向后再复制n个,比如:(w+), 1,第一个分组(w+),后面的1表示将前面的分组捕获的结果在后面再次依样捕获1个。

>>> regex = r'(w+),1' >>> m = re.search(regex, 'foo,foo') >>> m <_sre.SRE_Match object; span=(0, 7), match='foo,foo'> >>> m.group(1) 'foo'

在这个示例中,分组(w+)已经捕获了字符串foo,在正则表达式中的1表示向后引用前面的捕获结果,即可以继续在字符串中搜索,能够要再捕获一个foo。再如:

>>> m = re.search(regex, 'qux,qux') >>> m <_sre.SRE_Match object; span=(0, 7), match='qux,qux'> >>> m.group(1) 'qux'

如果搜索的字符串是foo,qux,由于捕获第一个foo之后,继续在字符串中搜索,无法得到foo了,所以,会搜索失败。

>>> m = re.search(regex, 'foo,qux') >>> print(m) None

参考资料:https://realpython.com/regex-python/

---来自腾讯云社区的---用户7315084

关于作者: 瞎采新闻

这里可以显示个人介绍!这里可以显示个人介绍!

热门文章

留言与评论(共有 0 条评论)
   
验证码: