上面我们已经看过了Python的正则式的很多基本用法。不过如果仅仅是上面那些规则的话,还是有很多情况下会非常麻烦,比如上面在讲前向界定和后向界定时,取夹在字母中间的数字的例子。用前面讲过的规则都很难达到目的,但是用了组以后就很简单了。
最基本的组是由一对圆括号括起来的正则式。比如上面匹配包夹在字母中间的数字的例子中使用的(\d+),我们再回顾一下这个例子:
>>> s = ‘aaa111aaa , bbb222 , 333ccc ‘ >>> re.findall (r'[a-z]+(\d+)[a-z]+' , s ) ['111']
可以看到findall函数只返回了包含在’()’中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。
除了最基本的形式外,我们还可以给组起个名字,它的形式是
‘(?P’代表这是一个Python的语法扩展’<…>’里面是你给这个组起的名字,比如你可以给一个全部由数字组成的组叫做’num’,它的形式就是’(?P<num>\d+)’。起了名字之后,我们就可以在后面的正则式中通过名字调用这个组,它的形式是
要注意,再次调用的这个组是已被匹配的组,也就是说它里面的内容是和前面命名组里的内容是一样的。
我们可以看更多的例子:请注意下面这个字符串各子串的特点。
>>> s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
我们看看下面的正则式会返回什么样的结果:
>>> re.findall( r'([a-z]+)\d+([a-z]+)' , s ) # 找出中间夹有数字的字母 [('aaa', 'aaa'), ('fff', 'ggg')] >>> re.findall( r '(?P[a-z]+)\d+(?P=g1)' , s )#找出被中间夹有数字的前后同样的字母 ['aaa'] >>> re.findall( r'[a-z]+(\d+)([a-z]+)' , s ) #找出前面有字母引导,中间是数字,后面是字母的字符串中的中间的数字和后面的字母 [('111', 'aaa'), ('777', 'ggg')]
我们可以通过命名组的名字在后面调用已匹配的命名组,不过名字也不是必需的。
正则式中的每个组都有一个序号,序号是按组从左到右,从1开始的数字,你可以通过下面的形式来调用已匹配的组
比如上面找出被中间夹有数字的前后同样的字母的例子,也可以写成:
>>> re.findall( r’([a-z]+)\d+\1’ , s ) ['aaa']
结果是一样的。
我们再看一个例子
>>> s='111aaa222aaa111 , 333bbb444bb33' >>> re.findall( r'(\d+)([a-z]+)(\d+)(\2)(\1)' , s ) #找出完全对称的 数字-字母-数字-字母-数字 中的数字和字母 [('111', 'aaa', '222', 'aaa', '111')]
Python2.4以后的re模块,还加入了一个新的条件匹配功能
‘(?(id/name)yes-pattern|no-pattern)’ 判断指定组是否已匹配,执行相应的规则
这个规则的含义是,如果id/name指定的组在前面匹配成功了,则执行yes-pattern的正则式,否则执行no-pattern的正则式。
举个例子,比如要匹配一些形如usr@mail 的邮箱地址,不过有的写成< usr@mail >即用一对<>括起来,有点则没有,要匹配这两种情况,可以这样写
>>> s=<usr1@mail1> usr2@maill2' >>> re.findall( r'(<)?\s*(\w+@\w+)\s*(?(1)>)' , s ) [('<', 'usr1@mail1'), ('', 'usr2@maill2')]
不过如果目标字符串如下
>>> s='<usr1@mail1> usr2@maill2 <usr3@mail3 usr4@mail4> < usr5@mail5 '
而你想得到要么由一对<>包围起来的一个邮件地址,要么得到一个没有被<>包围起来的地址,但不想得到一对<>中间包围的多个地址或不完整的<>中的地址,那么使用这个式子并不能得到你想要的结果
>>> re.findall( r'(<)?\s*(\w+@\w+)\s*(?(1)>)' , s ) [('<', 'usr1@mail1'), ('', 'usr2@maill2'), ('', 'usr3@mail3'), ('', 'usr4@mail4'), ('', 'usr5@mail5')]
它仍然找到了所有的邮件地址。
想要实现这个功能,单纯的使用findall有点吃力,需要使用其它的一些函数,比如match或search函数,再配合一些控制功能。这部分的内容将在下面详细讲解。
小结:以上基本上讲述了Python正则式的语法规则。虽然大部分语法规则看上去都很简单,可是稍不注意,仍然会得到与期望大相径庭的结果,所以要写好正则式,需要仔细的体会正则式规则的含义后不同规则之间细微的差别。
详细的了解了规则后,再配合后面就要介绍的功能函数,就能最大的发挥正则式的威力了。