正则虐我千百遍,我待正则如初恋

/ 0评 / 0

本文算是python正则表达式操作指南的读书笔记。

简单模式

1.字符匹配
元字符:.^*+?{[]|()
[]:常用来指定一个字符类别,或称字符集。
例如[abc][a-c]匹配a,b,c中的任意一个字符。注意,在[]中$也是作为普通字符存在。

此外,可以用补集的方式来匹配不在范围内的字符,其做法是把""作为类别的首个字符;其他地方,^只会匹配^字符自身。例如[^5]就是匹配除5之外的任意字符。

最重要的元字符应该是"".在""后面加上不同的字符,可以表示不同的含义。比如说,可以用于取消元字符,以便在模式中对其进行匹配。还有一些预定义字符集也是很有用的,例如:

d 匹配任何十进制数;它相当于类 [0-9]。
D 匹配任何非数字字符;它相当于类 [^0-9]。
s 匹配任何空白字符;它相当于类 [ tnrfv]。
S 匹配任何非空白字符;它相当于类 [^ tnrfv]。
w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]。

最后一个元字符是"."。它可以匹配除了换行符之外的任何字符!牛逼与坑爹并存的结合体。

2.重复
在匹配的过程中难免重复,这就体现出重复的作用了。
首先讨论一下"*".它并不匹配字符"*";相反,它指定前一个字符可以被匹配零次或更多次,而不是只有一次。
来,举个栗子:ca*t就可以匹配ct,cat,caat,caaat……(传说可以匹配超过20亿个"a"字符,当然,一般没人这么干)

另外一个中啊哟的元字符是"+",表示匹配一次或更多次。
来,举个栗子:ca*t就可以匹配cat,caat,caaat……(传说可以匹配超过20亿个"a"字符,当然,一般没人这么干)
+与*的区别就是a这个字符必须得出现一次才能匹配。

还有个"?",表示匹配一次或零次。

最复杂的重复限定符是{m, n},表示至少有m个重复,最多重复n个。忽略m的时候,会认为下边界是0.

3.其他

剩下来要讨论的一部分元字符是零宽界定符(zero-width assertions)。它们并不会使引擎在处理字符串时更快;相反,它们根本就没有对应任何字符,只是简单的成功或失败。举个例子, b 是一个在单词边界定位当前位置的界定符(assertions),这个位置根本就不会被 b 改变。这意味着零宽界定符(zero-width assertions)将永远不会被重复,因为如果它们在给定位置匹配一次,那么它们很明显可以被匹配无数次。

|

可选项,或者 "or" 操作符。如果 A 和 B 是正则表达式,A|B 将匹配任何匹配了 "A" 或 "B" 的字符串。| 的优先级非常低,是为了当你有多字符串要选择时能适当地运行。Crow|Servo 将匹配"Crow" 或 "Servo", 而不是 "Cro", 一个 "w" 或 一个 "S", 和 "ervo"。

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

^

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

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

#!python
>>> print re.search('^From', 'From Here to Eternity')

>>> print re.search('^From', 'Reciting From Memory')
None
$

匹配行尾,行尾被定义为要么是字符串尾,要么是一个换行字符后面的任何位置。

#!python
>>> print re.search('}$', '{block}')

>>> print re.search('}$', '{block} ')
None
>>> print re.search('}$', '{block}n')

匹配一个 "$",使用 $ 或将其包含在字符类中,如[$]。

A

只匹配字符串首。当不在 MULTILINE 模式,A 和 ^ 实际上是一样的。然而,在 MULTILINE 模式里它们是不同的;A 只是匹配字符串首,而 ^ 还可以匹配在换行符之后字符串的任何位置。

Z

Matches only at the end of the string.
只匹配字符串尾。

b

单词边界。这是个零宽界定符(zero-width assertions)只用以匹配单词的词首和词尾。单词被定义为一个字母数字序列,因此词尾就是用空白符或非字母数字符来标示的。

下面的例子只匹配 "class" 整个单词;而当它被包含在其他单词中时不匹配。

#!python
>>> p = re.compile(r'bclassb')
>>> print p.search('no class at all')

>>> print p.search('the declassified algorithm')
None
>>> print p.search('one subclass is')
None
当用这个特殊序列时你应该记住这里有两个微妙之处。第一个是 Python 字符串和正则表达式之间最糟的冲突。在 Python 字符串里,"b" 是反斜杠字符,ASCII值是8。如果你没有使用 raw 字符串时,那么 Python 将会把 "b" 转换成一个回退符,你的 RE 将无法象你希望的那样匹配它了。下面的例子看起来和我们前面的 RE 一样,但在 RE 字符串前少了一个 "r" 。

#!python
>>> p = re.compile('bclassb')
>>> print p.search('no class at all')
None
>>> print p.search('b' + 'class' + 'b')

第二个在字符类中,这个限定符(assertion)不起作用,b 表示回退符,以便与 Python 字符串兼容。

B

另一个零宽界定符(zero-width assertions),它正好同 b 相反,只在当前位置不在单词边界时匹配。

4.分组

在匹配过程中,需要将结果进行分组的时候就需要利用到"(" 和 ")"元字符来标识的。例如(ab)*就将匹配零或更多个重复的"ab".

引用:
python正则表达式操作指南

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注