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}$。使用了正向肯定预查,可以使用.*,且预查不消耗字符。