模块级别的函数
不必每次都先创建样式对象再调用函数,re模块同时提供了高层次的函数如match(),search(),findall(),sub()等等,这些函数带有相应样式方法相同的参数,只要把相应样式字符串当作第一个参数,同样可以返回None或MatchObject对象。
>>>printre.match(r'From\s+','Fromageamk')
None
>>>re.match(r'From\s+','FromamkThuMay1419:12:101998')
<_sre.SRE_Matchobjectat0x...>
在括号中,这些函数创建了一个样式对象,然后调用了基于此对象的方法,同时将编译后的样式对象存储在缓冲区中,这样以后使用相同的样式对象就可以更快。
是应当直接使用这些模块函数,还是应当先创建样式对象再调用它们呢?这取决于样式对象调用的频率和你自己的编译风格:如果仅仅使用一次,模块函数会更方便;如果程序中包含多个样式对象,或者需要在不同的地方调用,最好还是先赋值给一个变量再随后使用该变量。例如标准库中的例子(来自xmllib.py):
ref=re.compile(...)
entityref=re.compile(...)
charref=re.compile(...)
starttagopen=re.compile(...)
我通常更喜欢使用编译过的对象,即使在只使用一次的情况下,不过有些人在这方面就认真多了。
编译标记符
使用编译标记符可以调整正则表达式某些方面的运行方式。在re模块里,有两种标记形式:长形式如IGNORECASE,以及简短形式,只有一个字母,如L,它和Perl的样式修饰符相同,例如re.VERBOSE的简短形式是re.X。多个标记符可以使用位运算OR,如re.I|re.M同时设定了两个标记符I和M。
下面表格显示了这些标记符,详细解释见后:
标记符 | 含义 |
DOTAL | 使句号.匹配任何字符,包含新行,如果没有则匹配除新行外的所有字符 |
IGNORECASE,I | 区分大小写,例如[A-Z]同样会匹配小写字母,Spam可以匹配Spam,spam或spAM等。注意不包括环境设置,除非设置了LOCALE标记符。 |
LOCALE,L | 匹配当前语言环境设置。这种情况下\w,\W,\b和\B基于当前的环境设置。环境(Locale)是C库中帮助书写程序时考虑到语言差异的概念。例如在处理法语时,可能会想用\w+匹配单词,但其实\w只能匹配[A-Za-z],对于法语中的特殊字母不能匹配,但是如果正确配置了系统并选择了法语环境,特定的C语言函数会将这些特殊法语字母当作一个英文字母。简言之,设置LOCALE标签可以使用这些C语言函数处理\w以匹配法语字母,不过会降低运行速度。 |
ULTILINE,M | 多行匹配,影响^和$。(^和$将在“其他元字符”一节中介绍)通常^只匹配字符串的开头,$只匹配字符串的结尾以及在新行(如果存在)前字符串的结尾。当此标记设定,^将匹配字符串的开头以及字符串的的一行开始,而$将匹配字符串的结尾以及每一行的结尾。 |
VERBOSE,X | 详细显示模式,组织清晰以利于理解。这个标记符允许更加灵活的书写格式以利于阅读。当设定此标记符时,正则表达式中的空格将被忽略,除非空格是在一个字符组合中或前面加了\,从而允许组织和缩进更加清晰。它同时允许在正则表达式中添加注释,注释以#(注意不能在字符组合或前面有\)标记,它将被匹配引擎忽略。 |
UNICODE,U | 在这种情况下一些控制符如\w、\b、\s和\d基于Unicode编码。 |
下面是一个使用re.VERBOSE的例子,是不是可读性大大提高了?
charref=re.compile(r"""
&[#] #数字的起始
(
0[0-7]+ #八进制
|[0-9]+ #十进制
|x[0-9a-fA-F]+ #十六进制
)
; #分号
""",re.VERBOSE)
如果不使用此模式,正则表达式如下所示:
charref=re.compile("&#(0[0-7]+"
"|[0-9]+"
"|x[0-9a-fA-F]+);")
在上面的例子中,虽然使用了Python中的字符串自动连接特性将正则表达式分解为几个小字符串,但相比使用re.VERBOSE模式仍然难于阅读。
正则表达式样式的更多应用
目前为止我们仅仅介绍了正则表达式的一部分特征,本节中将介绍更多的元字符,以及使用分组来检索匹配的文字。
其他元字符
本节将介绍前面没有涉及的一些元字符。
这些元字符包括一些“零宽度断言”——它们不会使匹配引擎扫描字符串,事实上它们根本不占用字符,例如\b表示当前位置是一个单词的边界,而这个边界并没有因为\b而改变,这意味着“零宽度断言”不应当被重复多次,因为如果它们在一个给定的位置上匹配成功,那么也肯定能在无数次重复后匹配成功。
|表示“或”操作符。如果A和B是正则表达式,A|B将匹配那些能够匹配A或B的字符串,为了使交换包含多个字符的字符串更加恰当,它的优先级很低。Crow|Servo将匹配Crow或者Servo,而非Cro,w,S或者ervo。
为了能够匹配字符|,使用\|或者[|]。
^匹配一行的开始。除非设定了MULTILINE标记符,它只会匹配字符串的起始;在MULTILINE模式下,它也会匹配字符串中的一行开始处。
例如,如果希望在一行起始处匹配单词From,应当使用正则表达式^From。
>>>printre.search('^From','FromHeretoEternity')
<_sre.SRE_Matchobjectat0x...>
>>>printre.search('^From','RecitingFromMemory')
None
$匹配一行的结尾——字符串的结尾或者换行处。
>>>printre.search('}$','{block}')
<_sre.SRE_Matchobjectat0x...>
>>>printre.search('}$','{block}')
None
>>>printre.search('}$','{block}\n')
<_sre.SRE_Matchobjectat0x...>
如果试图匹配字符$,应当使用\$或者[$]。
\A只匹配字符串的起始处。当不是在MULTILINE模式时,\A和^效果相同;而在MULTILINE模式下则不同——\A依然仅仅匹配字符串的起始处,而^将匹配字符串的新行起始处或字符串起始处。
\Z仅仅匹配字符串的结束。
\b表示匹配单词边界。它是一个“零宽度断言”,表明仅仅匹配单词的开始或者结尾。这里的“单词”表示字母序列,所以“单词结尾”表明遇见了空白或非单词的字符。
下面的实例中仅仅在字符串是单纯的一个单词时才会匹配,当包含在其他单词中则不能匹配。
>>>p=re.compile(r'\bclass\b')
>>>printp.search('noclassatall')
<_sre.SRE_Matchobjectat0x...>
>>>printp.search('thedeclassifiedalgorithm')
None
>>>printp.search('onesubclassis')
None
当使用\b特殊序列时应当注意两点:第一,这是Python的字符串与正则表达式序列冲突最严重的一个,前者中\b表示退格,其ASCII值为8,如果不使用纯字符串模式,Python会将\b解释为退格,那么正则表达式的行为将不是你想要的。下面这个例子焉上面的例子相同,但是去掉了样式字符串前面的r:
>>>p=re.compile('\bclass\b')
>>>printp.search('noclassatall')
None
>>>printp.search('\b'+'class'+'\b')
<_sre.SRE_Matchobjectat0x...>
第二,在字符集合中,这个断言没有用,\b表示退格字符以与Python的字符串相兼容。
\B是另外一个零字符断言,与\b意义相反,它仅仅在当前位置上不是单词边界时才进行匹配。