现在的位置: 首页 > 综合 > 正文

正则表达式之常用量词

2013年10月08日 ⁄ 综合 ⁄ 共 2584字 ⁄ 字号 评论关闭

正则表达式之常用量词

{m,n}是通用形式的量词,正则表达式还有三个常用量词,分别是+?*。它们的形态虽然不同于{m,n},功能却是相同的(也可以把它们理解为“量词简记法”),具体说明见表2-2

 

表2-2  常用量词

常用量词

{m,n}等价形式

说明

*

{0,}

可能出现,也可能不出现,出现次数没有上限

+

{1,}

至少出现1次,出现次数没有上限

?

{0,1}

至多出现1次,也可能不出现

 

在实际应用中,在很多情况只需要表示这三种意思,所以常用量词的使用频率要高于{m,n},下面分别说明。

大家都知道,美国英语和英国英语有些词的写法是不一样的,比如traveler和traveller,如果希望“通吃”traveler和traveller,就要求第2l是“至多出现1次,也可能不出现”的,正好使用?量词:travell?er,如例2-4所示。

 

例2-4  量词?的应用

re.search(r"^travell?er$","traveler") != None 
#  => True

re.search(r"^travell?er$","traveller") != None    
#  => True

 

其实这样的情况还有很多,比如favor和favour、color和colour。此外还有很多其他应用场合,比如http和https,虽然是两个概念,但都是协议名,可以用https?匹配;再比如表示价格的字符串,有可能是100也有可能是100,可以用¥?100匹配。

量词也广泛应用于解析HTML代码。HTML是一种“标签语言”,它包含各种各样的tag(标签),比如<head>、<img>、<table>等,这些tag的名字各异,形式却相同:从<开始,到>结束,在<和>之间有若干字符,“若干”的意思是长度不确定,但不能为0<>并不是合法的tag),也不能是>字符。如果要用一个正则表达式匹配所有的tag,需要用<匹配开头的<,用>匹配结尾的>,用[^>]+匹配中间的“若干字符”,所以整个正则表达式就是<[^>]+>,程序如例2-5所示。

 

例2-5  量词+的应用

re.search(r"^<[^>]+>$","<bold>") != None      
#  => True

re.search(r"^<[^>]+>$","</table>") != None        
#  => True

re.search(r"^<[^>]+>$","<>") != None          
#  => False

 

类似的,也可以使用正则表达式匹配双引号字符串。不同的是,双引号字符串的两个双引号之间可以没有任何字符,""也是一个完全合法的双引号字符串,应该使用量词*,于是整个正则表达式就成了"[^"]*",程序见例2-6

 

例2-6  量词*的应用

re.search(r"^\"[^\"]*\"$","\"some\"") != None 
#  => True

re.search(r"^\"[^\"]*\"$","\"\"") != None         
#  => True

注:字符串之中表示双引号需要转义写成\",这并不是正则表达式中的规定,而是为字符串转义考虑。

 

量词的使用有很多学问,不妨多看几个tag匹配的例子:tag可以粗略分为open tagclose
tag
,比如<head>就是open tag,而</html>就是close tag;另外还有一类标签是self-closing
tag
,比如<br/>。现在来看分别匹配这三类tag的正则表达式。

open tag的特点是以<开头,然后是“若干字符”(但不能以/开头),最后是>,所以对应的正则表达式是<[^/][^>]*>;注意:因为[^/]必须匹配一个字符,所以“若干字符”中其他部分必须写成[^>]*,否则它无法匹配名字为单个字符的标签,比如<b>。

close tag的特点是以<开头,之后是/字符,然后是“若干字符(但不能以/开头)”,最后是>,所以对应的正则表达式是</[^>]+>

self-closing tag的特点是以<开头,中间是“若干字符”,最后是/>,所以对应的正则表达式是<[^>]+/>。注意:这里不是<[^>/]+/>,排除型字符组只排除>,而不排除/,因为要确认的只是在结尾的>之前出现/,如果写成<[^>/]+/>,则要求tag内部不能出现/,就无法匹配<img
src="http://somehost/picture" />这类的
tag了。

2-3列出了匹配几类tag的表达式。

 

表2-3  各类tag的匹配

匹配所有tag的表达式

tag分类

匹配分类tag的表达式

 

<[^>]+>

open tag

<[^/>][^>]*>

close tag

</[^>]+>

self-closing tag

<[^>/]+/>

 

对比表格中“匹配所有tag的表达式”和“匹配分类tag的表达式”,可以发现它们的模式是相近的,只是细节上有差异。也就是说,通过变换字符组和量词,可以准确控制正则表达式能匹配的字符串的范围,达到不同的目的。这其实是使用正则表达式时的一条根本规律:使用合适的结构(包括字符组和量词),精确表达自己的意图,界定能匹配的文本。

再仔细观察,你或许会发现,匹配open tag的表达式,也可以匹配self-closing tag<[^/][^>]*>能够匹配<br/>,因为[^>]*并不排除对/的匹配。那么将表达式改为<[^/][^>]*[^/]>,就保证匹配的open
tag
不会以/>结尾了。

不过这会产生新的问题:<[^/][^>]*[^/]>能匹配的tag,在<和>之间出现了两个[^/],上一章已经讲过,排除型字符组表示“在当前位置,匹配一个没有列出的字符”,所以tag里的字符串必须至少包含两个字符,这样就无法匹配<u>了。

仔细想想,真正要表达的意思是,在tag内部的字符串不能以/开头,也不能以/结尾,如果这个字符串只包含一个字符,那么它既是开头,又是结尾,使用两个排除型字符组显然是不合适的,看起来没办法解决了。实际上,只是现有的知识还不足够解决这个问题而已,在第68页有这个问题的详细解法。

 

 

本文节选自《正则指引》一书余晟著

图书详细信息:http://blog.csdn.net/broadview2006/article/details/7569554

抱歉!评论已关闭.