python正则re模块详解-.pdf
《python正则re模块详解-.pdf》由会员分享,可在线阅读,更多相关《python正则re模块详解-.pdf(20页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、编辑 简介Python 自 1.5 版本起增加了re 模块,它提供Perl 风格的正则表达式模式。Python 1.5 之前版本则是通过regex 模块提供Emecs 风格的模式。Emacs 风格模式可读性稍差些,而且功能也不强,因此编写新代码时尽量不要再使用regex 模块,当然偶尔你还是可能在老代码里发现其踪影。就其本质而言,正则表达式(或RE)是一种小型的、高度专业化的编程语言,(在Python 中)它内嵌在Python 中,并通过re 模块实现。使用这个小型语言,你可以为想要匹配的相应字符串集指定规则;该字符串集可能包含英文语句、e-mail 地址、TeX 命令或任何你想搞定的东西。然
2、后你可以问诸如“这个字符串匹配该模式吗?”或“在这个字符串中是否有部分匹配该模式呢?”。你也可以使用RE 以各种方式来修改或分割字符串。正则表达式模式被编译成一系列的字节码,然后由用C 编写的匹配引擎执行。在高级用法中,也许还要仔细留意引擎是如何执行给定RE,如何以特定方式编写RE 以令生产的字节码运行速度更快。本文并不涉及优化,因为那要求你已充分掌握了匹配引擎的内部机制。哈哈正则表达式语言相对小型和受限(功能有限),因此并非所有字符串处理都能用正则表达式完成。当然也有些任务可以用正则表达式完成,不过最终表达式会变得异常复杂。碰到这些情形时,编写Python 代码进行处理可能反而更好;尽管Py
3、thon 代码比一个精巧的正则表达式要慢些,但它更易理解。编辑 简单模式我们将从最简单的正则表达式学习开始。由于正则表达式常用于字符串操作,那我们就从最常见的任务:字符匹配下手。有关正则表达式底层的计算机科学上的详细解释(确定性和非确定性有限自动机),你可以查阅编写编译器相关的任何教科书。字符匹配大多数字母和字符一般都会和自身匹配。例如,正则表达式test 会和字符串“test”完全匹配。(你也可以使用大小写不敏感模式,它还能让这个RE 匹配“Test”或“TEST”;稍后会有更多解释。)这个规则当然会有例外;有些字符比较特殊,它们和自身并不匹配,而是会表明应和一些特殊的东西匹配,或者它们会影
4、响到RE 其它部分的重复次数。本文很大篇幅专门讨论了各种元字符及其作用。这里有一个元字符的完整列表;其含义会在本指南馀下部分进行讨论。.$*+?|()我们首先考察的元字符是 和 。它们常用来指定一个字符类别,所谓字符类别就是你想匹配的一个字符集。字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。例如,abc 将匹配 a,b,或 c 中的任意一个字符;也可以用区间a-c来表示同一字符集,和前者效果一致。如果你只想匹配小写字母,那么RE 应写成a-z.元字符在类别里并不起作用。例如,akm$将匹配字符 a,k,m,或$中的任意一个;$通常用作元字符,但在字符类别里,其特性被除
5、去,恢复成普通字符。你可以用补集来匹配不在区间范围内的字符。其做法是把 作为类别的首个字符;其它地方的 只会简单匹配 字符本身。例如,5 将匹配除5 之外的任意字符。也许最重要的元字符是反斜杠。做为Python 中的字符串字母,反斜杠后面可以加不同的字符以表示不同特殊意义。它也可以用于取消所有的元字符,这样你就可以在模式中匹配它们了。举个例子,如果你需要匹配字符 或,你可以在它们之前用反斜杠来取消它们的特殊意义:或。一些用 开始的特殊字符所表示的预定义字符集通常是很有用的,象数字集,字母集,或其它非空字符集。下列是可用的预设特殊字符:d 匹配任何十进制数;它相当于类0-9。D 匹配任何非数字字
6、符;它相当于类0-9。s 匹配任何空白字符;它相当于类 tnrfv。S 匹配任何非空白字符;它相当于类 tnrfv。w 匹配任何字母数字字符;它相当于类a-zA-Z0-9_。W 匹配任何非字母数字字符;它相当于类a-zA-Z0-9_。这样特殊字符都可以包含在一个字符类中。如,s,.字符类将匹配任何空白字符或,或.。本节最后一个元字符是.。它匹配除了换行字符外的任何字符,在alternate 模式(re.DOTALL)下它甚至可以匹配换行。.通常被用于你想匹配“任何字符”的地方。编辑 重复正则表达式第一件能做的事是能够匹配不定长的字符集,而这是其它能作用在字符串上的方法所不能做到的。不过,如果那
7、是正则表达式唯一的附加功能的话,那么它们也就不那么优秀了。它们的另一个功能就是你可以指定正则表达式的一部分的重复次数。我们讨论的第一个重复功能的元字符是*。*并不匹配字母字符*;相反,它指定前一个字符可以被匹配零次或更多次,而不是只有一次。举个例子,ca*t 将匹配ct(0 个 a 字符),cat(1 个 a),caaat(3 个 a 字符)等等。RE 引擎有各种来自C 的整数类型大小的内部限制,以防止它匹配超过2 亿个a 字符;你也许没有足够的内存去建造那么大的字符串,所以将不会累计到那个限制。象*这样地重复是“贪婪的”;当重复一个RE 时,匹配引擎会试着重复尽可能多的次数。如果模式的后面部
8、分没有被匹配,匹配引擎将退回并再次尝试更小的重复。一步步的示例可以使它更加清晰。让我们考虑表达式abcd*b。它匹配字母a,零个或更多个来自类bcd中的字母,最后以b 结尾。现在想一想该RE 对字符串abcbd 的匹配。Step Matched Explanation 1 a a 匹配模式2 abcbd 引擎匹配bcd*,并尽其所能匹配到字符串的结尾3 Failure 引擎尝试匹配b,但当前位置已经是字符的最后了,所以失败4 abcb 退回,bcd*尝试少匹配一个字符。5 Failure 再次尝次b,但在当前最后一位字符是d。6 abc 再次退回,bcd*只匹配bc。7 abcb 再次尝试b,
9、这次当前位上的字符正好是b RE 的结尾部分现在可以到达了,它匹配abcb。这证明了匹配引擎一开始会尽其所能进行匹配,如果没有匹配然后就逐步退回并反复尝试RE 剩下来的部分。直到它退回尝试匹配bcd 到零次为止,如果随后还是失败,那么引擎就会认为该字符串根本无法匹配RE。另一个重复元字符是+,表示匹配一或更多次。请注意*和+之间的不同;匹配零或更多次,所以根本就可以不出现,而+则要求至少出现一次。用同一个例子,ca+t 就可以匹配cat(1 个 a),caaat(3 个 a),但不能匹配ct。还有更多的限定符。问号?匹配一次或零次;你可以认为它用于标识某事物是可选的。例如:home-?brew
10、 匹配homebrew 或 home-brew。最复杂的重复限定符是m,n,其中m 和 n 是十进制整数。该限定符的意思是至少有m 个重复,至多到n 个重复。举个例子,a/1,3b 将匹配a/b,a/b 和 a/b。它不能匹配ab 因为没有斜杠,也不能匹配a/b,因为有四个。你可以忽略m 或 n;因为会为缺失的值假设一个合理的值。忽略m 会认为下边界是0,而忽略n 的结果将是上边界为无穷大-实际上是先前我们提到的2 兆,但这也许同无穷大一样。细心的读者也许注意到其他三个限定符都可以用这样方式来表示。0,等同于*,1,等同于+,而 0,1则与?相同。如果可以的话,最好使用*,+,或?。很简单因为
11、它们更短也再容易懂。编辑 使用正则表达式现在我们已经看了一些简单的正则表达式,那么我们实际在Python 中是如何使用它们的呢?re 模块提供了一个正则表达式引擎的接口,可以让你将REs 编译成对象并用它们来进行匹配。编辑 编译正则表达式正则表达式被编译成RegexObject 实例,可以为不同的操作提供方法,如模式匹配搜索或字符串替换。#!python import re p=pile(ab*)print p pile()也接受可选的标志参数,常用来实现不同的特殊功能和语法变更。我们稍后将查看所有可用的设置,但现在只举一个例子:#!python p=pile(ab*,re.IGNORECAS
12、E)RE 被做为一个字符串发送给pile()。REs 被处理成字符串是因为正则表达式不是Python 语言的核心部分,也没有为它创建特定的语法。(应用程序根本就不需要REs,因此没必要包含它们去使语言说明变得臃肿不堪。)而re 模块则只是以一个C 扩展模块的形式来被Python 包含,就象socket 或zlib 模块一样。将 REs 作为字符串以保证Python 语言的简洁,但这样带来的一个麻烦就是象下节标题所讲的。编辑 反斜杠的麻烦在早期规定中,正则表达式用反斜杠字符()来表示特殊格式或允许使用特殊字符而不调用它的特殊用法。这就与Python 在字符串中的那些起相同作用的相同字符产生了冲突
13、。让我们举例说明,你想写一个RE 以匹配字符串section,可能是在一个LATEX 文件查找。为了要在程序代码中判断,首先要写出想要匹配的字符串。接下来你需要在所有反斜杠和元字符前加反斜杠来取消其特殊意义。字符阶段section 要匹配的字符串section 为 pile 取消反斜杠的特殊意义section 为字符串取消反斜杠简单地说,为了匹配一个反斜杠,不得不在RE 字符串中写,因为正则表达式中必须是,而每个反斜杠按Python 字符串字母表示的常规必须表示成。在REs 中反斜杠的这个重复特性会导致大量重复的反斜杠,而且所生成的字符串也很难懂。解决的办法就是为正则表达式使用Python 的
14、 raw 字符串表示;在字符串前加个 r 反斜杠就不会被任何特殊方式处理,所以rn 就是包含 和 n 的两个字符,而n 则是一个字符,表示一个换行。正则表达式通常在Python 代码中都是用这种raw 字符串表示。常规字符串Raw 字符串ab*rab*section rsection w+s+1 rw+s+1 执行匹配一旦你有了已经编译了的正则表达式的对象,你要用它做什么呢?RegexObject 实例有一些方法和属性。这里只显示了最重要的几个,如果要看完整的列表请查阅Python Library Reference 方法/属性作用match()决定RE 是否在字符串刚开始的位置匹配searc
15、h()扫描字符串,找到这个RE 匹配的位置findall()找到RE 匹配的所有子串,并把它们作为一个列表返回finditer()找到RE 匹配的所有子串,并把它们作为一个迭代器返回如果没有匹配到的话,match()和 search()将返回None。如果成功的话,就会返回一个MatchObject 实例,其中有这次匹配的信息:它是从哪里开始和结束,它所匹配的子串等等。你可以用采用人机对话并用re 模块实验的方式来学习它。如果你有Tkinter 的话,你也许可以考虑参考一下Tools/scripts/redemo.py,一个包含在Python 发行版里的示范程序。首先,运行Python 解释器
16、,导入re 模块并编译一个RE:#!python Python 2.2.2(#1,Feb 10 2003,12:57:01)import re p=pile(a-z+)p 现在,你可以试着用RE 的 a-z+去匹配不同的字符串。一个空字符串将根本不能匹配,因为+的意思是“一个或更多的重复次数”。在这种情况下match()将返回None,因为它使解释器没有输出。你可以明确地打印出match()的结果来弄清这一点。#!python p.match()print p.match()None 现在,让我们试着用它来匹配一个字符串,如tempo。这时,match()将返回一个MatchObject。因此
17、你可以将结果保存在变量里以便后面使用。#!python m=p.match(tempo)print m 现在你可以查询MatchObject 关于匹配字符串的相关信息了。MatchObject 实例也有几个方法和属性;最重要的那些如下所示:方法/属性作用group()返回被RE 匹配的字符串start()返回匹配开始的位置end()返回匹配结束的位置span()返回一个元组包含匹配(开始,结束)的位置试试这些方法不久就会清楚它们的作用了:#!python m.group()tempo m.start(),m.end()(0,5)m.span()(0,5)group()返回RE 匹配的子串。st
18、art()和 end()返回匹配开始和结束时的索引。span()则用单个元组把开始和结束时的索引一起返回。因为匹配方法检查到如果RE 在字符串开始处开始匹配,那么start()将总是为零。然而,RegexObject 实例的search 方法扫描下面的字符串的话,在这种情况下,匹配开始的位置就也许不是零了。#!python print p.match(:message)None m=p.search(:message);print m m.group()message m.span()(4,11)在实际程序中,最常见的作法是将MatchObject 保存在一个变量里,然后检查它是否为None,
19、通常如下所示:#!python p=pile(.)m=p.match(string goes here)if m:print Match found:,m.group()else:print No match 两个RegexObject 方法返回所有匹配模式的子串。findall()返回一个匹配字符串行表:#!python p=pile(d+)p.findall(12 drummers drumming,11 pipers piping,10 lords a-leaping)12,11,10 findall()在它返回结果时不得不创建一个列表。在Python 2.2 中,也可以用 findit
20、er()方法。#!python iterator=p.finditer(12 drummers drumming,11.10.)iterator for match in iterator:.print match.span().(0,2)(22,24)(29,31)编辑 模块级函数你不一定要产生一个RegexObject 对象然后再调用它的方法;re 模块也提供了顶级函数调用如match()、search()、sub()等等。这些函数使用RE 字符串作为第一个参数,而后面的参数则与相应RegexObject 的方法参数相同,返回则要么是None 要么就是一个MatchObject 的实例。#
21、!python print re.match(rFroms+,Fromage amk)None re.match(rFroms+,From amk Thu May 14 19:12:10 1998)Under the hood,这些函数简单地产生一个RegexOject 并在其上调用相应的方法。它们也在缓存里保存编译后的对象,因此在将来调用用到相同RE 时就会更快。你将使用这些模块级函数,还是先得到一个RegexObject 再调用它的方法呢?如何选择依赖于怎样用RE 更有效率以及你个人编码风格。如果一个RE 在代码中只做用一次的话,那么模块级函数也许更方便。如果程序包含很多的正则表达式,或在
22、多处复用同一个的话,那么将全部定义放在一起,在一段代码中提前编译所有的REs 更有用。从标准库中看一个例子,这是从xmllib.py 文件中提取出来的:#!python ref=pile(.)entityref=pile(.)charref=pile(.)starttagopen=pile(.)我通常更喜欢使用编译对象,甚至它只用一次,but few people will be as much of a purist about this as I am。编辑 编译标志编译标志让你可以修改正则表达式的一些运行方式。在re 模块中标志可以使用两个名字,一个是全名如IGNORECASE,一个是缩
23、写,一字母形式如I。(如果你熟悉Perl 的模式修改,一字母形式使用同样的字母;例如re.VERBOSE 的缩写形式是re.X。)多个标志可以通过按位OR-ing 它们来指定。如re.I|re.M 被设置成I 和 M 标志:这有个可用标志表,对每个标志后面都有详细的说明。标志含义DOTALL,S 使.匹配包括换行在内的所有字符IGNORECASE,I 使匹配对大小写不敏感LOCALE,L 做本地化识别(locale-aware)匹配MULTILINE,M 多行匹配,影响 和$VERBOSE,X 能够使用REs 的 verbose 状态,使之被组织得更清晰易懂I IGNORECASE 使匹配对大
24、小写不敏感;字符类和字符串匹配字母时忽略大小写。举个例子,A-Z也可以匹配小写字母,Spam 可以匹配Spam,spam,或 spAM。这个小写字母并不考虑当前位置。L LOCALE 影响w,W,b,和 B,这取决于当前的本地化设置。locales 是 C 语言库中的一项功能,是用来为需要考虑不同语言的编程提供帮助的。举个例子,如果你正在处理法文文本,你想用w+来匹配文字,但w 只匹配字符类A-Za-z;它并不能匹配 或?。如果你的系统配置适当且本地化设置为法语,那么内部的C 函数将告诉程序 也应该被认为是一个字母。当在编译正则表达式时使用LOCALE 标志会得到用这些C 函数来处理w 后的编
25、译对象;这会更慢,但也会象你希望的那样可以用w+来匹配法文文本。M MULTILINE(此时 和$不会被解释;它们将在4.1 节被介绍.)使用 只匹配字符串的开始,而$则只匹配字符串的结尾和直接在换行前(如果有的话)的字符串结尾。当本标志指定后,匹配字符串的开始和字符串中每行的开始。同样的,$元字符匹配字符串结尾和字符串中每行的结尾(直接在每个换行之前)。S DOTALL 使.特殊字符完全匹配任何字符,包括换行;没有这个标志,.匹配除了换行外的任何字符。X VERBOSE 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。当该标志被指定时,在RE 字符串中的空白符被忽略,除非该空白
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- python 正则 re 模块 详解
限制150内