编译模式
一个模式可以通过编译(变成一个内部的表达)来提高检索的速度。这一步不是强制的,而是推荐对大量的文本进行使用。让我们看看findall的正则模式,而后用编译的模式(rgx):
正则模式如下:
>>> re.findall(“[Hh]ello”,”Hello world, hello Python,!”)
[’Hello’, ’hello’]
编译的模式如下:
>>> rgx = re.compile(“[Hh]ello”)
>>> rgx.findall(“Hello world, hello Python,!”)
[’Hello’, ’hello’]
编译后的模块(这里就是rgx)有许多在re模块中的方法:
>>> rgx = re.compile(“[Hh]ello”)
>>> rgx.search(“Hello world, hello Python,!”)
<_sre.SRE_Match object at 0xb6f494f0>
>>> rgx.match(“Hello world, hello Python,!”)
<_sre.SRE_Match object at 0xb6f493d8>
>>> rgx.findall(“Hello world, hello Python,!”)
[’Hello’, ’hello’]
组(Groups)
有时你需要多于一个模式相匹配,这可以通过分组完成。组是由一组括号(“()”)来标记的。组可以被“捕获”(“命名”或“无名”)和“非捕获”,它们之间的区别,以后将会明确的。
一个“捕获”的组用于当你需要提取一组的内容时。组可以被groups捕获。不要混淆group与groups。
正则表达式字符串中(也就是模式中)的第一对括号就是第1组,第二对括号就是第2组。想group()匹配对象方法传入整数1或者2,就可以取得匹配文本的不同部分。向group()传入0或者不传入参数,将返回整个匹配的文本。例如:
>>> import re
>>> seq = "ATATAAGATGCGCGCGCTTATGCGCGCA"
>>> rgx = re.compile("(GC){3,}(TTAT)") #这里模式"(GC){3,}(TTAT)"中,第一个分组就是(GC),第二个分组也就是(TTAT)
>>> result = rgx.search(seq)
>>> result.group(1) #传入整数1,获得第一个分组的匹配结果
'GC'
>>> result.group(2) #传入整数2,获得第二个分组的匹配结果
'TTAT'
>>> result.group() #不传入参数,返回整个匹配的结果
'GCGCGCGCTTAT'
>>> result.groups() #注意group()和groups()的区别,group() 不传入参数,返回的是整个匹配的结果,而groups()返回的是模式中每个分组匹配结果组成的元组。
('GC', 'TTAT')
>>> rgx = re.compile(“((GC){3,})”) #这个模式中有2个分组,从左边往右边数,左边第一个括号就是第一个分组,左边第2个括号就是第2个分组。
>>> result = rgx.search(seq)
>>> result.groups()
(’GCGCGCGC’, ’GC’)
所有在模式中的两个组都被提取了(从左边到右边计数)。正是这样的方法因为该每个组是“捕获”的。如果你不需要内部的子组(如“GC”),你可以注释为“非捕获”。这就需要在组的开头用“?:”:
>>> rgx = re.compile(“((?:GC){3,})”)
>>> result = rgx.search(seq)
>>> result.groups()
(’GCGCGCGC’,)
indall的行为也不同。没有组时,它返回一个匹配的字符串的列表。如果有一个组在模式中,它返回一个这个组的列表。如果有多个组在模式中,它返回一个元组的列表:
>>> rgx = re.compile(“TAT”) # No group at all.
>>> rgx.findall(seq) # This returns a list of matching strings.
[’TAT’, ’TAT’]
seq = “ATATAAGATGCGCGCGCTTATGCGCGCA”
>>> rgx = re.compile(“(GC){3,}”) # One group. Return a list
>>> rgx.findall(seq) # with the group for each match.
[’GC’, ’GC’] ########返回group匹配的内容,(GC)在seq中的GCGCGCGC和GCGCGC都可以匹配到,但只返回(GC)匹配的结果,也就是GC
>>> rgx = re.compile(“((GC){3,})”) # Two groups. Return a
>>> rgx.findall(seq) # list with tuples for each match.
[(’GCGCGCGC’, ’GC’), (’GCGCGC’, ’GC’)] ########模式中2个group,在seq的GCGCGCGC分别返回(GC){3,}和(GC),在seq的GCGCGC分别返回 (GC){3,}和(GC)
>>> rgx = re.compile(“((?:GC){3,})”) # Using a non-capturing
>>> rgx.findall(seq) # group to get only the matches.
[’GCGCGCGC’, ’GCGCGC’]
组还可以被标记以备后用。来给出一个组的名字用?P:<name>。代码9.2显示了怎样用这个特性:
例9.2:
import re
rgx = re.compile("(?P<TBX>TATA..).*(?P<CGislands>(?:GC){3,})")
seq = "ATATAAGATGCGCGCGCTTATGCGCGCA"
result = rgx.search(seq)
print(result.group('CGislands'))
print(result.group('TBX'))
这个程序返回:
GCGCGC
TATAGA