很久之前曾经写过一篇:[Python:正则表达式的应用一综述] 但一直都没有写接下来的具体使用,所以这篇文章就首先来介绍如何快速使用re模块来匹配字符串。刚开始我会直接使用例子来实践,可能有人有所埋怨使用的函数,但相信你随着介绍的深入,你会理解的。
一、自身匹配
大多数字母和字符一般都会和自身匹配。例如,正则表达式 test 会和字符串“test”完全匹配,当然这是正则表达式肯定能够做到的,但这也太大材小用了吧。
例:匹配ourunix>>> s = "ourunix"
>>> s1 = "ourrunix"
>>> regex = "ourunix"
>>> p = re.compile(regex)
>>> p.findall(s)
['ourunix']
>>> p.findall(s1)
[]
说明:s和s1是用来测试的字符串,regex是指定的正则表达式,p是编译之后的正则表达式对象,p的findall函数返回能够找到的所有符合regex的字符串。
二、元字符
自身匹配规则当然会有例外,因为有些字符比较特殊,它们和自身并不匹配,而是会表明应和一些特殊的东西匹配,或者它们会影响到正则表达式其它部分的重复次数。
这是一个基本的元字符列表. ^ $ * + ? { [ ] \ | ( )
下面我们就来围绕这个元字符列表展开介绍。
三、匹配字符集
使用"[]"匹配字符集
使用[]可以使正则表达式里面的一个字符匹配一个字符集,比如我想匹配“cxt”这个x可以为任意a,b,c中的一个,即cat、cbt、cct等都可以满足,那么我就可以使用[]的规则来标识这个字符集a、b、c。
例:匹配cxt>>> import re
>>> s = "we are cat, cAt, c1t, cbt, cct."
>>> regex = "c[abc]t"
>>> p = re.compile(regex)
>>> p.findall(s)
['cat', 'cbt', 'cct']
需要说明的是,[]字符集中的字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。例如上例的[abc] 将匹配"a","b",或 "c"中的任意一个字符,这个也可以用区间[a-c]来表示同一字符集,和上例的效果一致。如果你只想匹配一个小写字母,那么正则表达式应写成 [a-z]。
另外元字符在类别里并不起作用。例如,[akm$]这个字符集将匹配字符"a", "k", "m", 或 "$" 中的任意一个;"$"通常用作元字符,但在字符类别里,其特性被除去,恢复成普通字符。
使用"^"匹配不在字符集
当然你可以用补集来匹配不在字符集范围内的字符。其做法是把"^"作为类别的首个字符;其它地方的"^"只会简单匹配 "^"字符本身。例如,[^5] 将匹配除 "5" 之外的任意字符。
例:匹配cxt,其中x是除a,b,c中的一个>>> import re
>>> s = "we are cat, cAt, c1t, cbt, cct."
>>> regex = "c[^a-c]t"
>>> p = re.compile(regex)
>>> p.findall(s)
['cAt', 'c1t']
"\"的特殊意义
也许最重要的元字符是反斜杠"\"。
1、做为 Python 中的字符串字母,反斜杠后面可以加不同的字符以表示不同特殊意义。
2、转义。它也可以用于取消所有的元字符,这样你就可以在模式中匹配它们了。举个例子,如果你需要匹配字符 "[" 或 "\",你可以在它们之前用反斜杠来取消它们的特殊意义: \[ 或 \\。
一些用 "\" 开始的特殊字符所表示的预定义字符集通常是很有用的,象数字集,字母集,或其它非空字符集。
下列是可用的预设特殊字符:\d 匹配任何十进制数;它相当于类 [0-9]
\D 匹配任何非数字字符;它相当于类 [^0-9]
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
例:匹配cxt,其中x可以是任何字母数字或者是!>>> import re
>>> s = "we are cat, cAt, c1t, cbt, cct, c!t, a!t."
>>> regex = "c[\w!]t"
>>> p = re.compile(regex)
>>> p.findall(s)
['cat', 'cAt', 'c1t', 'cbt', 'cct', 'c!t']
"."的用法
它匹配除了换行字符外的任何字符,"." 通常被用于你想匹配“任何字符”的地方。
四、匹配可重复的字符
正则表达式第一件能做的事是能够匹配不定长的字符集,而这是其它能作用在字符串上的方法所不能做到的,至少我目前没有遇到过哪个字符串方法可以这么做。
使用"*"匹配零次或更多次
* 并不匹配字母字符 "*",相反,它指定前一个字符可以被匹配零次或更多次,而不是只有一次。
例:匹配cxxxxx...t,其中xxxxx...为任意个a,比如ct,cat,caat,caaaaaaat都是符合的import re
>>> s = "we are cat, cAt, c1t, ct, caaaaaaaaaat, caat"
>>> regex = "ca*t"
>>> p = re.compile(regex)
>>> p.findall(s)
['cat', 'ct', 'caaaaaaaaaat', 'caat']
说明:正则表达式引擎有各种来自C的整数类型大小的内部限制,以防止它匹配超过20亿个 "a" 字符,你也许没有足够的内存去建造那么大的字符串,所以将不会累计到那个限制。
使用"+"至少匹配一次
上例中的regex如果将*换成+的话,结果将不会出现ct。
使用"?"匹配零次或一次
略
使用重复限定符是 {m,n}
最复杂的重复限定符是 {m,n},其中 m 和 n 是十进制整数。该限定符的意思是至少有 m 个重复,至多到 n 个重复。
例:匹配cxxxxx...t,其中xxxxx...为1~3个a或者不,比如cat,caat,cbt,cabbt都是符合的,但是ct,caaaaaaat是不符合import re
>>> s = "we are cat, cAt, cabt, cbbt, c1t, ct, cabct, caaaaaaaaaat, caat"
>>> regex = "c[ab]{1,3}t"
>>> p = re.compile(regex)
>>> p.findall(s)
['cat', 'cabt', 'cbbt', 'caat']
说明:你可以忽略 m 或 n,忽略 m 会认为下边界是 0,而忽略 n 的结果将是上边界为无穷大 -- 实际上是先前我们提到的20亿,但这也许同无穷大一样。
细心的读者也许注意到其他三个限定符都可以用这样方式来表示。 {0,} 等同于 *,{1,} 等同于 +,而{0,1}则与 ? 相同。如果可以的话,最好使用 *,+,或?。很简单因为它们更短也更容易懂。
五、Python中使用正则表达式
事实上通过上面一些简单模式的介绍,你应该对Python中如何使用正则表达式有了一个大致的了解。
编译正则表达式import re
>>> regex = "c[ab]{1,3}t"
>>> p = re.compile(regex)
>>> print p
使用re的comiple可以将指定正则表达式编译成RegexObject实例,当然re.compile() 也接受可选的标志参数,常用来实现不同的特殊功能和语法变更。比如:p = re.compile(regex, re.IGNORECASE)
>>> print p
开始执行匹配
现在你已经有了RegexObject实例,那么你就可以使用其开始执行匹配了,这里列举了一些简单的函数:match() 决定正则表达式是否在字符串刚开始的位置匹配
search() 扫描字符串,找到这个正则表达式匹配的位置
findall() 找到正则表达式匹配的所有子串,并把它们作为一个列表返回
finditer() 找到正则表达式匹配的所有子串,并把它们作为一个迭代器返回
说明:如果没有匹配到的话,match() 和 search() 将返回 None。如果成功的话,就会返回一个 `MatchObject` 实例,其中有这次匹配的信息:它是从哪里开始和结束,它所匹配的子串等等。
完