python 正则表达式

正则表达式描述了一种字符串匹配的模式。

1 为什么要使用正则表达式

a. 数据验证

验证手机号,银行卡号等。

b. 替换文本

正则查找特定源文本,将其替换为目标文本。

c. 提取子串

从给定字符串中提取目标子串。

2 正则表达式-语法

\s  匹配任何单个空白字符,包括tab键和换行符。

\S  匹配任何非空白字符。

\w  匹配包括[a-zA-Z0-9_]。(大小写英文字母、数字、下划线)

\W  匹配任何非\w中的字符。(除了大小写英文字母、数组、下划线之外的特殊字符)

\d  匹配包括[0-9]的数字。

\D 匹配任何非\d的数字。

a. 特殊字符

$  匹配字符串的结束位置,若设置了匹配的多行属性,$也匹配\n,\r。

^  匹配字符串的开始位置。 

()  标记子表达式的开始和结束。

+  匹配前面的子表达式1次或多次。

*  匹配前面的子表达式0次或多次。

?  匹配前面的子表达式0次或1次。

\  将下一个字符标记为或特殊字符,或原义字符,或反向引用。例如:\n匹配换行符,\1表示同前面的括号子表达式。

.  匹配除了换行符\n之外的任意单字符。

|  标记两项之间的选择。

[  方括号表达式的开始标记。

{  标记限定表达式的开始。

b. 限定符

限制匹配次数。

*  匹配前面的子表达式0次或多次。

+  匹配前面的子表达式1次或多次。

?  匹配前面的子表达式0次或1次。

{n}  准确匹配,匹配前面的子表达式n次。

{n,}  匹配前面的子表达式至少n次。

{n,m}  匹配前面的子表达式,至少n次,至多m次。

*和+限定符都是贪婪的,它们尽可能多的匹配字符。只有在它们后面加一个?,就能实现非贪婪或最小匹配。

例:对于正则 [a-z]+,若对字符串abcde匹配,则会尽可能匹配最长的结果,即贪婪匹配,匹配结果为:abcde。若是对abcde使用正则[a-z]+?匹配,则会匹配最短满足条件的结果,为a

c. 定位符

$  标记字符串的开始。

^  标记字符串的结尾。

\b  匹配一个单词的边界。即单词与空格之间的位置。

例如:

/\bHel/  可以匹配 "Hello World",但是不能匹配"Haahel World",因为Hel需要出现在单词的开头。

/Hel\b/ 无法匹配"Hello World",但是可以匹配"ollHel World",因为Hel需要出现在单词的末尾。

\B  匹配非单词的边界。

例如:

/\BHel/  可以匹配 "HaaHelooo World",也可以匹配 "oooHelHello World",但是不能匹配"Hello World",因为Hel匹配单词的非边界。

因此,\B非单词边界运算符,与位置无关,匹配不关心是在单词的开头还是结尾。

3 选择

圆括号将一些项括起来,相邻选择项之间用 | 分隔。但是使用圆括号有一个缺点,就是相关的匹配会被缓存,此时可以用?:加在第一个选项的前面,从而消除这种副作用。

例如:匹配AABA格式的字符串,且将A提取出来,定义正则="(\w)\1(?:\w)\1",可以满足要求。

4 反向引用

就是对前面出现的分组进行再一次引用。反向引用最有用的应用就是匹配字符串中重复出现的内容。

例如:匹配AA形式的字符串,定义正则="(\w)\1",使用反向表达式\1表示引用前面的子表达式\w,而不用重复写,尤其在正则表达式比较繁杂的时候更有效。

5 re模块

re.compile(pattern, flags)可以编译正则表达式,其中flags是如下一些常量参数,如果要设置多个,可以用|分隔,例如:re.compile(r"^abc(\d)898$", re.I|re.M),表示不区分大小写,并且采用多行匹配。

r 表示原字符串的意思,不用加转义字符。

re.I  ignorecase,表示不区分大小写。

re.M multiline,表示多行匹配。

6 捕获组与非捕获组(正向预查,反向预查)

(pattern) 捕获组,表示匹配pattern并且捕获匹配结果。

例:this (is) a (happy) day  的意思是:匹配 this is a happy day,并且有两个字模式匹配 is 与 happy,并且这两个子模式的匹配会存储下来。

(?:pattern) 非捕获组,匹配pattern但是不需要捕获匹配结果。消耗字符。

例:this (?:is) a (?:happy) day  的意思是:匹配 this is a happy day,并且有两个字模式匹配 is 与 happy,但是这两个子模式的匹配不存储。

(?=pattern) 非捕获组,正向肯定预查。lookahead,在任何匹配pattern的字符串开始处匹配查找字符串,匹配结果不存储,预查不消耗字符。

例:hello(?=world)  的意思是:匹配hello,且后面紧跟的是world。

(?!pattern) 非捕获组,正向否定预查。lookahead,在任何不匹配pattern的字符串开始处匹配查找字符串,匹配结果不存储,预查不消耗字符。

例:[0-9a-z]{2}(?!aa)  的意思是:匹配2个字符,且后面紧跟的不是aa。

例:a(?!a)  的意思是:匹配a,且a后面跟的不是a。

(?<=pattern) 非捕获组,反向肯定预查。lookbehind,与正向肯定预查类似,只是方向相反。pattern中不能有+,*等不定长度的量词。预查不消耗字符。

例:(?<=hello)world  的意思是:匹配world,且world前面是hello。

(?<!pattern) 非捕获组,反向否定预查。lookbehind,与正向否定预查类似,只是方向相反。pattern中不能有+,*等不定长度的量词。预查不消耗字符。

例:(?<!hello)world  的意思是:匹配world,且world前面不是hello。

7 实例解析

a. 检测密码强度

  • 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$。使用了正向肯定预查,可以使用.*,且预查不消耗字符。
  • 强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$。使用了正向肯定预查,可以使用.*,且预查不消耗字符。
posted @ 2019-09-25 11:40  江湖凶险  阅读(1090)  评论(0编辑  收藏  举报