注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Bioinformatics home

 
 
 

日志

 
 

python 正则表达式 学习 5  

2010-01-28 08:47:06|  分类: python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

1.  Python正则式的基本用法

1.1基本规则

1.2重复

1.2.1最小匹配与精确匹配

1.3前向界定与后向界定

1.4组的基本知识

2.  re模块的基本函数

2.1使用compile加速

2.2 match和search

2.3 finditer

2.4 字符串的修改与替换

3.  更深入的了解re的组与对象

3.1编译后的Pattern对象

3.2 组与Match对象

3.2.1组的名字与序号

3.2.2 Match对象的方法

4.  更多的资料


初学Python,对Python的文字处理能力有很深的印象,除了str对象自带的一些方法外,就是正则表达式这个强大的模块了。但是对 于初学者来说,要用好这个功能还是有点难度,我花了好长时间才摸出了点门道。由于我记性不好,很容易就忘事,所以还是写下来比较好一些,同时也可以加深印 象,整理思路。

由于我是初学,所以肯定会有些错误,还望高手不吝赐教,指出我的错误。

1 Python正则式的基本用法

Python的正则表达式的模块是 ‘re’,它的基本语法规则就是指定一个字符序列,比如你要在一个字符串s=’123abc456’ 中查找字符串 ’abc’,只要这样写:

>>> import re

>>> s='123abc456eabc789'

>>> re.findall(r’abc’,s)

结果就是:

['abc', 'abc']

这里用到的函数 ”findall(rule , target [,flag] )” 是个比较直观的函数,就是在目标字符串中查找符合规则的字符串。第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项(选项功能将在 compile函数的说明中详细说明)。返回结果结果是一个列表,中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。

为什么要用r’ ..‘字符串(raw字符串)? 由于正则式的规则也是由一个字符串定义的,而在正则式中大量使用转义字符’\’,如果不用raw字符串,则在需要写一个’\’的地方,你必须得写成’ \\’,那么在要从目标字符串中匹配一个’\’的时候,你就得写上4个’\’成为’\\\\’!这当然很麻烦,也不直观,所以一般都使用r’’来定义规则 字符串。当然,某些情况下,可能不用raw字符串比较好。

以上是个最简单的例子。当然实际中这么简单的用法几乎没有意义。为了实现复杂的规则查找,re规定了若干语法规则。它们分为这么几类:

功能字符 :    ‘.’ ‘*’ ‘+’ ‘|’ ‘?’ ‘^’ ‘$’ ‘\’ 等,它们有特殊的功能含义。特别是’\’字符,它是转义引导符号,跟在它后面的字符一般有特殊的含义。

规则分界符: ‘[‘ ‘]’ ‘(’ ‘)’ ‘{‘ ‘}’ 等,也就是几种括号了。

预定义转义字符集: “\d”  “\w” “\s” 等等,它们是以字符’\’开头,后面接一个特定字符的形式,用来指示一个预定义好的含义。

其它特殊功能字符: ’#’ ‘!’ ‘:’ ‘-‘等,它们只在特定的情况下表示特殊的含义,比如(?# …)就表示一个注释,里面的内容会被忽略。

下面来一个一个的说明这些规则的含义,不过说明的顺序并不是按照上面的顺序来的,而是我认为由浅入深,由基本到复杂的顺序来编排的。同时为了直观,在说明的过程中尽量多举些例子以方便理解。

1.1 基本规则

‘[‘  ‘]’ 字符集合设定符

首先说明一下字符集合设定的方法。由一对方括号括起来的字符,表明一个字符集合,能够匹配包含在其中的任意一个字符。比如 [abc123],表明字符’a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’都符合它的要求。可以被匹配。

在’[‘ ‘]’中还可以通过 ’-‘ 减号来指定一个字符集合的范围,比如可以用[a-zA-Z]来指定所以英文字母的大小写,因为英文字母是按照从小到大的顺序来排的。你不可以把大小的顺序颠倒了,比如写成[z-a]就不对了。

如果在’[‘ ‘]’里面的开头写一个 ‘^’ 号,则表示取非,即在括号里的字符都不匹配。如[^a-zA-Z]表明不匹配所有英文字母。但是如果 ‘^’不在开头,则它就不再是表示取非,而表示其本身,如[a-z^A-Z]表明匹配所有的英文字母和字符’^’。

‘|’    或规则

将两个规则并列起来,以‘|’连接,表示只要满足其中之一就可以匹配。比如

[a-zA-Z]|[0-9] 表示满足数字或字母就可以匹配,这个规则等价于 [a-zA-Z0-9]

注意:关于’|’要注意两点:

第一,           它在’[‘ ‘]’之中不再表示或,而表示他本身的字符。如果要在’[‘ ‘]’外面表示一个’|’字符,必须用反斜杠引导,即 ’\|’ ;

第二,           它的有效范围是它两边的整条规则,比如‘dog|cat’匹配的是‘dog’和’cat’,而不是’g’和’c’。如果想限定它的有效范围,必需使用一个 无捕获组 ‘(?: )’包起来。比如要匹配 ‘I have a dog’或’I have a cat’,需要写成r’I have a (?:dog|cat)’ ,而不能写成 r’I have a dog|cat’

>>> s = ‘I have a dog , I have a cat’

>>> re.findall( r’I have a (?:dog|cat)’ , s )

['I have a dog', 'I have a cat']                #正如我们所要的

下面再看看不用无捕获组会是什么后果:

>>> re.findall( r’I have a dog|cat’ , s )

['I have a dog', 'cat']                                   #它将’I have a dog’ 和’cat’当成两个规则了

至于无捕获组的使用,后面将仔细说明。这里先跳过。

‘.’    匹配所有字符

匹配除换行符’\n’外的所有字符。如果使用了’S’选项,匹配包括’\n’的所有字符。

       例:

       >>> s=’123 \n456 \n789’

       >>> findall(r‘.+’,s)

       ['123', '456', '789']

       >>> re.findall(r‘.+’ , s , re.S)

       ['123\n456\n789']

‘^’和’$’ 匹配字符串开头和结尾

注意’^’不能在‘[ ]’中,否则含意就发生变化,具体请看上面的’[‘ ‘]’说明。 在多行模式下,它们可以匹配每一行的行首和行尾。具体请看后面compile函数说明的’M’选项部分

‘\d’ 匹配数字

这是一个以’\’开头的转义字符,’\d’表示匹配一个数字,即等价于[0-9]

‘\D’ 匹配非数字

这个是上面的反集,即匹配一个非数字的字符,等价于[^0-9]。注意它们的大小写。下面我们还将看到Python的正则规则中很多转义字符的大小写形式,代表互补的关系。这样很好记。

‘\w’ 匹配字母和数字

匹配所有的英文字母和数字,即等价于[a-zA-Z0-9]。

‘\W’ 匹配非英文字母和数字

即’\w’的补集,等价于[^a-zA-Z0-9]。

‘\s’ 匹配间隔符

即匹配空格符、制表符、回车符等表示分隔意义的字符,它等价于[ \t\r\n\f\v]。(注意最前面有个空格)

‘\S’ 匹配非间隔符

即间隔符的补集,等价于[^ \t\r\n\f\v]

‘\A’ 匹配字符串开头

匹配字符串的开头。它和’^’的区别是,’\A’只匹配整个字符串的开头,即使在’M’模式下,它也不会匹配其它行的很首。

‘\Z’ 匹配字符串结尾

匹配字符串的结尾。它和’$’的区别是,’\Z’只匹配整个字符串的结尾,即使在’M’模式下,它也不会匹配其它各行的行尾。

例:

>>> s= '12 34\n56 78\n90'

>>> re.findall( r'^\d+' , s , re.M )          #匹配位于行首的数字

['12', '56', '90']

>>> re.findall( r’\A\d+’, s , re.M )        #匹配位于字符串开头的数字

['12']

>>> re.findall( r'\d+$' , s , re.M )          #匹配位于行尾的数字

['34', '78', '90']

>>> re.findall( r’\d+\Z’ , s , re.M )        #匹配位于字符串尾的数字

['90']

‘\b’ 匹配单词边界

它匹配一个单词的边界,比如空格等,不过它是一个‘0’长度字符,它匹配完的字符串不会包括那个分界的字符。而如果用’\s’来匹配的话,则匹配出的字符串中会包含那个分界符。

例:

>>> s =  'abc abcde bc bcd'

>>> re.findall( r’\bbc\b’ , s )         #匹配一个单独的单词 ‘bc’ ,而当它是其它单词的一部分的时候不匹配

['bc']                                           #只找到了那个单独的’bc’

>>> re.findall( r’\sbc\s’ , s )          #匹配一个单独的单词 ‘bc’

[' bc ']                                         #只找到那个单独的’bc’,不过注意前后有两个空格,可能有点看不清楚

‘\B’ 匹配非边界

和’\b’相反,它只匹配非边界的字符。它同样是个0长度字符。

接上例:

>>> re.findall( r’\Bbc\w+’ , s )     #匹配包含’bc’但不以’bc’为开头的单词

['bcde']                                       #成功匹配了’abcde’中的’bcde’,而没有匹配’bcd’

‘(?:)’ 无捕获组

当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用’(?:’ ‘)’把它包围起来,而不能仅仅只用一对括号,那样将得到绝对出人意料的结果。

例:匹配字符串中重复的’ab’

>>> s=’ababab abbabb aabaab’

>>> re.findall( r’\b(?:ab)+\b’ , s )

['ababab']

如果仅使用一对括号,看看会是什么结果:

>>> re.findall( r’\b(ab)+\b’ , s )

['ab']

这是因为如果只使用一对括号,那么这就成为了一个组(group)。组的使用比较复杂,将在后面详细讲解。

‘(?# )’ 注释

Python允许你在正则表达式中写入注释,在’(?#’ ‘)’之间的内容将被忽略。

(?iLmsux) 编译选项指定

Python的正则式可以指定一些选项,这个选项可以写在findall或compile的参数中,也可以写在正则式里,成为正则式的一部分。这在某些情况下会便利一些。具体的选项含义请看后面的compile函数的说明。

此处编译选项’i’ 等价于IGNORECASE ,L 等价于 LOCAL ,m 等价于 MULTILINE ,s 等价于 DOTALL ,u 等价于 UNICODE , x 等价于 VERBOSE 。

请注意它们的大小写。在使用时可以只指定一部分,比如只指定忽略大小写,可写为 ‘(?i)’,要同时忽略大小写并使用多行模式,可以写为 ‘(?im)’。

另外要注意选项的有效范围是整条规则,即写在规则的任何地方,选项都会对全部整条正则式有效。

1.2 重复

正则式需要匹配不定长的字符串,那就一定需要表示重复的指示符。Python的正则式表示重复的功能很丰富灵活。重复规则的一般的形式是在一条字符规则后面紧跟一个表示重复次数的规则,已表明需要重复前面的规则一定的次数。重复规则有:

‘*’   0或多次匹配

表示匹配前面的规则0次或多次。

‘+’   1次或多次匹配

表示匹配前面的规则至少1次,可以多次匹配

例:匹配以下字符串中的前一部分是字母,后一部分是数字或没有的变量名字

>>> s = ‘ aaa bbb111 cc22cc 33dd ‘

>>> re.findall( r’\b[a-z]+\d*\b’ , s )             #必须至少1个字母开头,以连续数字结尾或没有数字

['aaa', 'bbb111']

注意上例中规则前后加了表示单词边界的’\b’指示符,如果不加的话结果就会变成:

>>> re.findall( r’[a-z]+\d*’ , s )

['aaa', 'bbb111', 'cc22', 'cc', 'dd']    #把单词给拆开了

大多数情况下这不是我们期望的结果。

‘?’   0或1次匹配

只匹配前面的规则0次或1次。

例,匹配一个数字,这个数字可以是一个整数,也可以是一个科学计数法记录的数字,比如123和10e3都是正确的数字。

>>> s = ‘ 123 10e3 20e4e4 30ee5 ‘

>>> re.findall( r’ \b\d+[eE]?\d*\b’ , s )

['123', '10e3']

它正确匹配了123和10e3,正是我们期望的。注意前后的’\b’的使用,否则将得到不期望的结果。

  评论这张
 
阅读(972)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017