Python中的正则表达式(3)

模块级别的函数

不必每次都先创建样式对象再调用函数,re模块同时提供了高层次的函数如match()search(),findall()sub()等等,这些函数带有相应样式方法相同的参数,只要把相应样式字符串当作第一个参数,同样可以返回NoneMatchObject对象。

>>>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同时设定了两个标记符IM

下面表格显示了这些标记符,详细解释见后:

标记符

含义

DOTAL

使句号.匹配任何字符,包含新行,如果没有则匹配除新行外的所有字符

IGNORECASE,I

区分大小写,例如[A-Z]同样会匹配小写字母,Spam可以匹配SpamspamspAM等。注意不包括环境设置,除非设置了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而改变,这意味着零宽度断言不应当被重复多次,因为如果它们在一个给定的位置上匹配成功,那么也肯定能在无数次重复后匹配成功。

|表示操作符。如果AB是正则表达式,A|B将匹配那些能够匹配AB的字符串,为了使交换包含多个字符的字符串更加恰当,它的优先级很低。Crow|Servo将匹配Crow或者Servo,而非CrowS或者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意义相反,它仅仅在当前位置上不是单词边界时才进行匹配。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值