Python——正则表达式(1)

本文译自官方文档:Regular Expression HOWTOhtml

全文下载:Python正则表达式基础python

=========================================================================================程序员

摘要
正则表达式

本篇文档是在Python中经过re模块使用正则表达式的引导手册,提供了一个比参考类库相应部分更详细的介绍。
数据库

=========================================================================================学习

1.简介
优化

正则表达式(也称为REs,regexes,或者regex  patterns)本质上是一个被嵌入到Python中的一个精细的、高度专业化的程序语言,并经过re模块提供给程序员使用。使用正则表达式,你须要为那些你想要匹配的字符串集合定制一些规则;这些集合可能包含英文句子、邮箱地址、TeX命令或者任何你想要的东西。而后你就会问相似于这样的问题:“这个字符串匹配这个模式吗?”或者“在这个字符串中有适合的模式来匹配吗?”你可使用正则表达式去修改一个字符串或者用各类各样的方式去分割字符串。spa


正则表达式模式被编译成一系列的字节码,而后由一个用C语言写的匹配引擎执行。对于高级的应用,你必需要注意对于一个给定的RE,引擎是如何执行的,并经过必定的方式来编写RE以便这些字节码运行地更快。但本篇文档不包含RE优化的内容,由于这些须要你对引擎内核有一个很好的理解。.net


正则表达式语言相对较小,也比较严格,因此并非全部的字符串处理任务均可以用正则表达式完成。有些任务能够用正则表达式作,可是表达式很是复杂。在这些状况下,你最好经过常规Python代码完成任务,虽然Python代码可能会比精心编写的正则表达式运行速度要慢,可是相对来讲,它更好理解。
code

=========================================================================================

2.简单的模式

咱们从学习最简单的正则表达式开始。因为正则表达式常被用于处理字符串,因此咱们由最多见的任务入手:字符匹配。


对于计算机科学中潜在的正则表达式的更多细节,你能够参考编写编译器的有关资料。

------------------------------------------------------------------------------------------------------------------------------------------------------------
2.1.字符匹配
大多数字符和字母会简单地匹配它们本身,好比,正则表达式test能够彻底匹配字符串test(你可使用不区分大小写模式,那么这个正则表达式也能够匹配Test或者TEST;稍后会介绍更多这方面的细节)。


固然这个规则也有例外,有一些字符是特殊的【元字符】,它们并不匹配它们自身。相反的,它们表示将要匹配一些不一样的东西,或者经过重复、改变意义等影响RE中的其余部分。本篇文档大部份内容都致力于讨论各类元字符和它们的用法。


这是元字符的完整列表,它们的意义将在随后讨论:

.  ^  $  *  +  ?  {  }  [  ]  \  |  (  )

咱们先看一下方括号 [ ] .它们指定一个【字符类】,用来存放你但愿匹配的字符集合。这些字符能够单独列出,一个连续范围内的字符也能够用横杠‘-’链接首尾两个字符指定。好比,[abc]能够匹配a,b或c,[a-c]也有一样的效果,后者使用范围表达式来指定与前者相同的字符集合。若是你只想匹配小写字母,那么你的正则表达式为[a-z]。


须要注意的是,元字符在方括号内不会被激活!好比,[akm$]能够匹配字符‘a’,‘k’,‘m’或者‘$’,咱们知道‘$’也是一个元字符,可是在方括号内,它就会失去它的特性,只会匹配它自身。


你也能够匹配未在方括号中列出的字符,这须要在方括号中的第一个字符前面加上‘^’脱字符号,方括号字符集合以外的字符能够简单地匹配‘^’符号。好比,[^5]能够匹配任何不是‘5’的字符。

可能最重要的元字符是反斜杠\。在Python常规语法中,反斜杠后面跟上不一样的字符表示特殊的序列。在正则表达式中也是同样,若是反斜杠后面跟着一个元字符,那么元字符的“特殊功能”将不会被触发。好比你须要去匹配一个  [ 或者 \ ,你能够在它们以前加上反斜杠 \ 以去掉它们的特殊语义:\ [ 或者 \\


有一些特殊的、经常使用的序列也以反斜杠开始,好比十进制数字,或者非空白的字符集合。

让咱们来举个例子:\w匹配全部字母数字字符,若是正则表达式以字节的形式表示,这至关于字符类[a-zA-Z0-9]。若是正则表达式是一个字符串,\w 会匹配全部在Unicode数据库中标记的为字母的字符。你在编译正则表达式的时候能够经过提供re.ASCII标志进一步限制 \w的定义。

下面列举一些反斜杠加字符构成的特殊序列(并不完整)。
\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]


这些序列能够被包含在一个字符类中,好比,[\s,.]是一个字符类,能够匹配任何空白字符,或者‘,’和‘.’

这部分最后的一个元字符是‘.’,它匹配除了换行符以外的任何字符,若是设置了re.DOTALL标志,它将匹配包含换行符在内的全部字符。

------------------------------------------------------------------------------------------------------------------------------------------------------------

2.2.重复的事情
可以匹配不一样的字符是正则表达式能够作的第一件事情,但Python字符串现有的方法却没法实现。然而,若是这是正则表达式惟一的优点,那么它也不会有太大的进步。它的另外一个强大的功能是你能够指定RE部分被重复的次数。

首先咱们来学习有重复做用的第一个元字符星号 * ,它并不匹配它自身,而是指定它的前一个字符重复0次或者屡次,而不是肯定的多少次。


好比,ca*t能够匹配ct(有0个a字符)、cat(有1个a字符)、caaat(有3 个a字符)等等。不过受到正则表达式引擎C语言中int类型的限制,‘a’字符的重复次数不能超过2亿次,然而咱们日常也用不到这么大的数据。


正则表达式的重复规则是贪婪的,当重复匹配一个RE时,匹配引擎会尽量多地去匹配,直到不匹配或者到告终尾,匹配引擎就会回退一个字符,而后再尝试匹配。


咱们经过例子来一步步地让这个概念更清晰。让咱们考虑一个正则表达式a[bcd]*b,它要先匹配字符‘a’,而后匹配0个或多个字符类[bcd]中的字符,最后以字符‘b’结尾。如今假如它要匹配字符串‘abcbd’:

步骤 匹配 解释
1 a 匹配RE的第一个字符a
2 abcbd 引擎尽量远地匹配[bcd]*,直到该字符串的结尾
3 Failure 引擎尝试去匹配b,但当前位置已是字符串的末尾了,因此失败
4 abcb 回退一个字符,因此[bcd]*匹配少一个字符
5 Failure 引擎再次尝试匹配b,可是当前位置最后一个字符是d,因此失败
6 abc 再次回退一个字符,因此[bdc]*只匹配bc
7 abcb 再次匹配b,这一次当前位置的字符正好是b,因此匹配成功
RE匹配完成,因此最终,RE匹配的结果是abcb。这个例子证实了上述的讨论,正则表达式引擎老是先尽量远的匹配重复的字符,若是不匹配,他将逐步回退,而后再次尝试去匹配RE剩余的部分,直到重复字符的个数为0,若是这时仍然匹配失败,引擎就会得出结论:这个字符串不匹配这个RE。


另外一个表示重复的元字符是加号 + ,它指定匹配它前面的字符1次或者屡次。这里要注意星号 * 和加号 + 的区别,星号 * 匹配0次或者屡次,因此被匹配的内容可能压根儿就不出现,可是加号 + 要求重复的字符至少出现1次。举一个简单的例子,ca+t能够匹配cat(1个a字符)、caaat(3个a字符),可是它不匹配ct。


还有两个表示重复的元字符,其中一个就是问号 ? ,它用于指定匹配它前面的字符0次或者1次,你能够认为它用于标志一个可选的字符。好比,home-?brew能够匹配homebrew或者home-brew。

最灵活的表示重复的限定符应该是{m,n},这里的m和n都是十进制数字。这表示它前面的字符至少重复m次,最多重复n次。好比,a/{1,3}b能够匹配a/b,a//b和a///b。可是它不匹配ab,由于ab没有斜杠,也不匹配a////b,由于它有4个斜杠超过了3个。


你也能够省略m或者n,在这种状况下,引擎会假定一个合理的替代值。省略m将默认下限为0,省略n将默认无上限,即上限无穷大——固然,根据上文提到的,它不能超过2亿。(译者注:还有一种使用方式,{n}指定它前面的字符重复n次)

聪明的读者可能已经发现了,上文提到的星号 *、加号 +和问号 ?均可以用这个限定符表示。{0,}与星号 * 做用同样,{1,}与加号 + 做用同样,{0,1}与问号 ? 做用同样。然而,在实际应用中,首选星号 * 、加号 + 和问号 ?,由于它们更短,效率更高。