Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
164 lines (95 sloc) 7.91 KB

Python正则表达式

Python自1.5版本起增加了re模块,提供Perl风格的正则表达式模式。Python 1.5之前的版本则是通过regex模块提供Emacs风格的模式。

就其本质而言,正则表达式是一种小型的,高度专业化的编程语言。

正则表达式模式被编译成一系列的字节码,然后由C编写的匹配引擎执行。正则表达式语言相对小型和受限(功能有限),因此并非所有字符串处理都能用正则表达式完成。当然也有些任务可以用正则表达式完成,不过最终表达式会变得异常复杂。

简单模式

字符匹配

大多数字母和字符一般都会和自身匹配。例如,正则表达式test会和字符串"test"完全匹配。(你也可以使用大小写不敏感模式,从而让这个RE匹配"Test"或"TEST")。

这个规则当然会有例外:有些字符比较特殊,它们和自身并不匹配,而是表明应和一些特殊的东西匹配,或者它们会影响到RE其他部分的重复次数。

元字符完整列表:

.^$*+?{[]\|()
  • [] : 常用来指定一个字符类别,所谓字符类别就是你想匹配的一个字符集。字符可以单个列出,也可以用"-"符号分隔的两个给定字符来表示一个字符区间。例如,[abc]将匹配"a","b","c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致。如果你只想匹配小写字母,那么RE应写成[a-z]。

元字符在类别里并不起作用。例如,[akm$]将匹配字符"a","k","m"或"$"中的任意一个。"$"通常用作元字符,但在字符类别里,其特性被除去,恢复成普通字符。

  • ^ : 你可以用补集来匹配不在区间范围内的字符。其做法是把"^"作为类别的首个字符;其他地方的"^"只会简单匹配"^"符号本身。例如,[^5]将匹配除"5"之外的任意字符。
  • \ : 也许最重要的元字符是反斜杠"\"。作为Python中的字符串字母,反斜杠后面可以加不同的字符以表示不同特殊意义。它也可以用于取消所有元字符,这样你就可以在模式中匹配它们了。

一些用"\"开始的特殊字符所表示的预定义字符集通常是很有用的,像数字集,字母集,或其他非空字符集。下列是可用的预设特殊字符:

\d 匹配任何十进制数:相当于类[0-9]
\D 匹配任何非数字字符:相当于类[^0-9]
\s 匹配任何空白字符:相当于类[\t\n\r\f\v]
\S 匹配任何非空白字符:相当于类[^\t\n\t\f\v]
\w 匹配任何字母数字字符:相当于类[a-zA-Z0-9]
\W 匹配任何非字母数字字符:相当于类[^a-zA-Z0-9]

这样,特殊字符都可以包含在一个字符类中。如,[\s,.]字符类将匹配任何空白字符或","或"."。

  • . : 匹配除了换行符外的任何字符,在alternate模式(re.DOTALL)下它甚至可以匹配换行。"."通常被用于你想匹配任何字符的地方。

重复

正则表达式第一件能做的事是能够匹配不定长的字符集,而这是其他能作用在字符串上的方法所做不到的。不过,如果那是正则表达式唯一的附加功能的话,那么它就不那么优秀了。它们的另一个功能就是你可以指定正则表达式的一部分的重复次数。

  • * : * 并不匹配"*" ,相反,它指定前一个字符可以被匹配零次或更多次,而不是只有一次。

像 * 这样的重复是"贪婪的";当重复一个RE时,匹配引擎会试着重复尽可能多的次数。如果模式的后面部分没有被匹配,匹配引擎将退回并再次尝试更小的重复。

  • + : 表示匹配一次或更多次。请注意 * 和 + 之间的不同。 * 匹配零或更多次,所以可以根本就不出现,而 + 则要求至少出现一次。
  • ? : 匹配一次或零次。你可以认为它用于标识某事物是可选的。
  • {m,n} : 最复杂的重复限定符,其中m和n是十进制整数。该限定符的意思是至少有m个重复,至多有n个重复。举个例子,a/{1,3}b将匹配"a/b","a//b","a///b"。

你可以忽略m或n;因为会为缺失值假设一个合理的值。忽略m会认为下边界是0,而忽略n的结果将是上边界为无穷大。

{0,}等同于 * ,{1,}等同于+,而{0,1}则与?相同。

使用正则表达式

re模块提供了一个正则表达式引擎的接口,可以让你将REs编译成对象并用它们来进行匹配。

编译正则表达式

>>> import re
>>> p = re.compile('ab*')
>>> p
<_sre.SRE_Pattern object at 0x917ef20>

re.compile()也接受可选的标志参数,常用来实现不同的特殊功能和语法变更。

反斜杠的麻烦

为了匹配一个反斜杠,不得不在RE字符串中写'\\\\',因为正则表达式中必须是"\\",而每个反斜杠在常规的Python字符串值中必须表示成"\\"。在REs中反斜杠的这个重复特性会导致大量重复的反斜杠,而且所生成的字符串也很难懂。

解决的办法就是为正则表达式使用Python的raw字符串表示,在字符串前加个"r",反斜杠就不会被任何特殊方式处理。

执行匹配

一旦有了已经编译了的正则表达式对象,就可以使用它的一些方法和属性。

  • match() 决定RE是否在字符串刚开始的位置匹配
  • search() 扫描字符串,找到这个RE匹配的位置
  • findall() 找到RE匹配的所有子串,并把它们作为一个列表返回
  • finditer() 找到RE匹配的所有子串,并把它们作为一个迭代器返回

如果没有匹配到的话,match()和search()将返回None。如果成功的话,就返回一个 _sre.SRE_Match object 实例,其中有这次匹配的信息:它是从哪里开始和结束,它所匹配的子串等等。

模块级函数

re模块也提供了顶级函数,如match(),search(),sub()等等。这些函数使用RE字符串作为第一个参数。

>>> print re.findall('\d+', "xiayf 1987 08 22 hello")
>>> ['1987', '08', '22']

编译标志

编译标志让你可以修改正则表达式的一些运行方式。在re模块中标志可以使用两种名字,一种是全名如IGNORECASE,一种是缩写,一个字母的形式如I。多个标志可以通过按位或|标志来连接。

  • DOTALL, S 使.匹配包括换行符在内的所有字符
  • IGNORECASE, I 使匹配对大小写不敏感
  • LOCALE, L 做本地化识别(locale-aware)匹配
  • MULTILINE, M 多行匹配,影响^和$
  • VERBOSE, X 能够使用REs的verbose状态

更多模式功能

更多的元字符

  • | : 如果A和B是正则表达式,A|B将匹配任何匹配了A或B的字符串。

为了匹配字母"|",可以用|,或将其包含在字符类中,如[|]

  • ^ : 匹配行首。除非设置MULTILINE标志,它只是匹配字符串的开始。在MULTILINE模式里,它也可以直接匹配字符串中的每个换行。

例如,如果你只希望匹配在行首单词"From",那么RE将用^From

>>> import re
>>> print re.search('^From', 'From Here to Etenity')
<_sre.SRE_Match object at 0xa162950>
>>> print re.search('^From', 'Reciting from Memory')
None
>>>
  • $ : 匹配行尾,行尾被定义为要么是字符串尾,要么是一个换行符后面的任何位置
  • \A : 只匹配字符串首。当不在MULTILINE模式,A和^实际上是一样的。然而,在MULTILINE模式里它们是不同的:A只是匹配字符串首,而^还可以匹配在换行符之后字符串的任何位置。
  • \Z : 只匹配字符串尾
  • \b : 单词边界。这是个零宽界定符。只用于匹配单词的词首和词尾。单词被定义为一个字母数字序列,因此词尾就是用空白符或非字母数字符来标示的。
  • \B : 另一个零宽界定符,它正好和b相反,只在当前位置不在单词边界时匹配。
Something went wrong with that request. Please try again.