接上篇,正则表达式的基本内容并不多,也许你以为你对正则表达式已经完全掌握了,那么我们来看一个例子:
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*")'
r'@(?:[A-Z0-9](?:[A-Z0-9-]{0,247}[A-Z0-9])?\.)+(?:[A-Z]{2,6}|[A-Z0-9-]{2,}(?<!-))$'
为了显示好看,分成了三排,上面这段正则表达式表示了对邮箱的验证,摘自Django源代码
这段正则的难易取决于大家自己的水平,但至少这段代码写的是比较复杂的,也警告着我们正则表达式还有很多细节需要我们的注意,记录如下
匹配任何字符,不包括换行,在DOTALL模式下,可以匹配换行
匹配开头和结尾,在MULTILINE模式下将匹配每一行的开头和结尾
匹配前一表达式重复m到n次,当忽略m的时候{,n}
将匹配0到n个,当忽略n时{m,}
将匹配m到无限多个
*? +? ??
,在默认情况下,*\+\?
都是贪婪的,将尽可能多的匹配,而在*\+\?
后面加上一个?
号,可以将改成非贪婪模式,将尽可能少的匹配。典型例子是.*
将匹配所有,.*?
将匹配空{m,n}?
,在默认情况下,{m,n}
也是贪婪的,将尽可能多的匹配,而{m,n}?
将尽肯能少的匹配[]
中的一个表达进行匹配,[abvc]
将匹配a\b\c\v
中的任何一个[(ab)(vc)]
这种形式,[]
中的元素只能单独存在,(
和)
将失去其效果(见下),如果想实现匹配(ab)
或(vc)
,请使用(ab|vc)
[]
中的特殊字符将失去效果,如[(+*)]
将只代表匹配(\+\*\)
中的任何一个\w
和\S
,代表任何数字与字母和代表非空字符^
,但必须使用在[]
中的第一个位置,才有效果,表示取反,如[^abc]表示除了a\b\c
以外的任何字符]
,当你想放一个]
在[]
中的时候,显然要对其进行转义[\]]
,同样,显然[
是不需要转义的[]
中支持-
符号,当他放在两个字符之间时,表示范围,如[a-z]
表示a到z的所有字符,-
前后可以是任何两个字符,只有前面的字符的ASCII值小于后面就可以,8进制表示的ASCII码也可以,比如[\001-\177]
其实就代表了键盘上的所有字符[z-a]
将会报错,因为不允许-
符号前面的ASCII值大于后面(\[\|)\?\.\*
需要转义,或者,可以放在[]
里,比如[|]
先尝试匹配|
左边的表达式,然后是右边。左右边界直到找到一个(
或)
为止,没有将找到边界
[]
中,可以实现最高优先级设置flag:re.I (ignore case), re.L (locale dependent), re.M (multi-line), re.S (dot matches all), re.U (Unicode dependent), and re.X
只抬高匹配优先级,但不放入re.group中
为group定名,可以在后面的表达式中使用,如:(?P<quote>['"]).*?(?P=quote)
,匹配双引号包含或单引号包含的字符串
引用在之前定名的group,示例见上
注释,将被完全忽略
(?=...)
,Isaac(?=Asimov)
将只匹配后面跟Asimov的Isaac(!=...)
,Isaac(?=Asimov)
将只匹配后面不跟Asimov的Isaac(?<=...)
,(?<=Asimov)Isaac
将只匹配前面为Asimov的Isaac(?<!...)
, (?<!Asimov)Isaac
将只匹配前面不为Asimov的Isaac(?<=a|b)Isaac
是被允许的,而(?<=a{3,5})Isaac
和(?<=a*)Isaac
是不允许的如果给定id或name的group存在,将匹配yes-pattern,否则将匹配no-pattern,如(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)
可以匹配<zhangdi@163.com>
或zhangdi@163.com
但是不会匹配<zhangdi@163.com
与(?P=name)
相似,按id引用之前的group,正则中group将从1开始按id编号,例子:(.+)[.]\1
将匹配55.55
或the.the
但不会匹配thethe
(
这是一个括号
^
[-!#$%&'*+/=?^_`{}|~0-9A-Z]+
开始符 可见字符中的1到多个
(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*
起始为一个点的可见字符0个到多个组合
|
或者,下面换了一种开头
^
"
开始符 双引号开头
([\001-\010\013\014\016-\037!#-\[\]-\177]
|
\\[\001-\011\013\014\016-\177]
去掉了垂直制表等特殊字符外的字符或以反斜杠开头就可以用垂直制表的字符集
)*
"
0到多个双引号结束
)
括号结束,到此为止,该正则表达式的所匹配的两种开头表述结束,以上部分可称为user_regex
@
@符承上启下
(?:[A-Z0-9](?:[A-Z0-9-]{0,247}[A-Z0-9])?\.)+
以大写字母或数字开头和结尾的,中间包含0到247个大写字母或数字的组合,1到多个,总是以点结束
(?:[A-Z]{2,6}
|
[A-Z0-9-]{2,}(?<!-))$
2到6个大写字母或2个以上包括短横杠的大写字母与数字组合,不能以短横杠开头
[1] 正则表达式在线验证
[1] Python官方文档