一.正则表达式之单个字符匹配
格式:lst = re.findall(正则表达式,要匹配的字符串)
预定义字符集 匹配内容
.匹配任意字符,除了换行符\n
\d匹配数字
\D匹配非数字
\w匹配字母或数字或下划线 (正则函数中,支持中文的匹配)
\W匹配非字母或数字或下划线
\s匹配任意的空白符
\S匹配任意非空白符
\n匹配一个换行符
\t匹配一个制表符
[]匹配中括号内列举的字符
字符组格式 说明 [默认必须从字符组中选一个]
|---|---|
[...] 匹配字符组中的字符|
[^...]匹配除了字符组内所有内容,之外的所有字符|
字符组内容|待匹配字符|匹配结果|说明|
|---|---|---|---|
[0123456789] 8 True字符组里枚举的各种字符,必须满足一个,否则返回假,不匹配
[abcdefg] 9False由于字符组中没有"9"字符,所以不匹配
[0-9] 7True可用 - 表示范围,[0-9] 和 [0123456789]是一个意思
[a-z] s True [a-z]匹配所有的小写字母
[A-Z]B True [A-Z]就表示所有的大写字母
[0-9a-fA-F]e True可以匹配数字,大小写形式的a-f. 该正则可验证十六进制
以下对上述匹配符合及使用方法进行举例:
import re
lst = re.findall(正则表达式, 要匹配的字符串)
\d 匹配数字
\D 匹配非数字
lst = re.findall("\d",\'123qwe456asd\')
print(lst)
#结果为: [\'1\', \'2\', \'3\', \'4\', \'5\', \'6\']
lst = re.findall("\D",\'123qwe456asd\')
print(lst)
#结果为:[\'q\', \'w\', \'e\', \'a\', \'s\', \'d\']
\w 字母,数字,下划线,包含中文(正则函数当中支持中文的匹配)
\W 匹配非字母或数字或下滑线
lst = re.findall(\'\w\',"d&*()qh321>wi")
print(lst)
#结果为:[\'d\', \'q\', \'h\', \'3\', \'2\', \'1\', \'w\', \'i\']
lst = re.findall(\'\W\',"d&*()qh321>wi")
#结果为:[\'&\', \'*\', \'(\', \')\', \'>\']
print(lst)
\s 匹配任意空白符
\S 匹配任意非空白符
strvar = """
"""
lst = re.findall(\'\s\',\' \')
print(lst)
#结果为: [\' \', \' \', \' \', \' \', \' \']
lst = re.findall("\S",strvar)
print(lst)
#结果为: [] #因为strvar里面没有空白符,没有匹配到内容,所有返回空列表
lst = re.findall("\S"," DQHh dq")
print(lst)
#结果为: [\'D\', \'Q\', \'H\', \'h\', \'d\', \'q\'] #是去掉空白符的所有字符形成的列表
\n 匹配换行
\t 匹配一个制表符
strvar = """
今天 天气 晴朗
"""
strvar2 = """
\t \tdqwdq
wd \t qq
"""
lst = re.findall(r"\n",strvar)
print(lst)
#结果为: [\'\n\', \'\n\']
print("==========")
lst = re.findall(r"\t",strvar2)
print(lst)
#结果为: [\'\t\', \'\t\', \'\t\']
# ###字符组练习, 必须从字符组选一个,如果一个都没有则匹配不成功
#举例: []匹配中括号内列举的字符
lst = re.findall("[123]","qwo1293dboh")
print(lst)
#结果为: [\'1\', \'2\', \'3\']
#中间的[a-g] 表示字母a到g中出现的字母就符合匹配条件
print(re.findall("a[a-g]b",\'aab abb acb adb\'))
#结果为:[\'aab\', \'abb\', \'acb\', \'adb\']
#在a与b之间是一位0到9的数就符合匹配
print(re.findall(\'a[0123456789]b\',\'a1b a2b acb ayb a9090909009b\'))
# 优化版:0123456789 => 0-9 等价
print(re.findall(\'a[0-9]b\',\'a1b a2b acb ayb a9090909009b\'))
#结果为:[\'a1b\', \'a2b\']
#在a与b之间的那一位字符是出现a到g的之间的字母就匹配
print(re.findall(\'a[abcdefg]b\',\'a1b a2b a3b acb ayb adb \'))
# 优化版:a b c d .... z => a-z
print(re.findall(\'a[a-g]b\',\'a1b a2b a3b acb ayb adb \'))
#结果为: [\'acb\', \'adb\']
print("================")
#中间的那一位字符可以是数字和大小写字母
print(re.findall(\'a[0-9a-zA-Z]b\',\'a-b aab aAb aWb aqba1b a8d a6b aaa5b231\'))
# 优化版: a-zA-Z => A-z 可以匹配所有大小写,但是有缺陷,一些特殊符号也匹配到了
#结果为: [\'aab\', \'aAb\', \'aWb\', \'aqb\', \'a1b\', \'a6b\', \'a5b\']
print(re.findall(\'[A-z]\',\'(\'))
#字母不包括( ,所有没有匹配到,返回空列表
#结果为: []
print(re.findall(\'[0-z]\',\'9\')) # 语法上允许,但是别这么用,没意义
#a与b 中间需要匹配两个字符一个是0-9,另外一个是 * # / 其中选一个
print(re.findall(\'a[0-9][*#/]b\',\'a1/b a2b a29b a56b a456bab\'))
#结果为: [\'a1/b\']
# ^ 字符组中的^ 代表除了的意思
print(re.findall(\'a[^-+*/]b\',"a%b ccaa*bda&bd"))
#结果为: [\'a%b\', \'a&b\']
二.匹配多个字符 => [元字符] 量词符号
量词
用法说明:
?重复0次或1次
+ 重复1次或多次 (至少1次)
*重复0次或多次 (任意次)
{n}重复n次
{n,}重复n次或更多次 (至少n次)
{n,m}重复n到m次
.* .+贪婪模式匹配
.*? .+?非贪婪模式匹配
# 贪婪匹配: 尽量多向后匹配 底层利用回溯算法
# 非贪婪匹配: 尽量少向后匹配
(1)量词加上问号?表示非贪婪 惰性匹配
(2).*?w 表示匹配任意长度任意字符遇到一个w就立即停止
import re
# (1) ? 匹配0个 或者 1 个 a
print(re.findall(\'a?b\', \'abbzab abb aab aaxqab\'))
# [\'ab\', \'b\', \'ab\', \'ab\', \'b\', \'ab\', \'ab\']
# (2) + 匹配1个或者多个a #必须要有a ,没有a的就不符合
print(re.findall(\'a+b\', \'abbzab abb aab aaxqab\'))
# [\'ab\', \'ab\', \'ab\', \'aab\', \'ab\']
# (3) * 匹配0个或者多个a
print(re.findall(\'a*b\', \'abbzab abb aab aaxqab\'))
# 可以没有,可以有,也可以多个
# [\'ab\', \'b\', \'ab\', \'ab\', \'b\', \'aab\', \'ab\']
# (4) {m,n} 匹配m个至n个a
print(re.findall(\'a{1,3}b\', \'abbzab abb aab aaxqab aaaaaab\'))
# 只有存在1个a或者以上到3个a的情况才匹配
# [\'ab\', \'ab\', \'ab\', \'aab\', \'ab\', \'aaab\']
print(re.findall(\'a{1}b\', \'abbzab abb aab aaxqab aaaaaaaaaab\'))
# [\'ab\', \'ab\', \'ab\', \'ab\', \'ab\'] 只匹配一个a的
print(re.findall(\'a{1,}b\', \'abbzab abb aab aaxqab aaaaaaaaaab\'))
# [\'ab\', \'ab\', \'ab\', \'aab\', \'ab\', \'aaaaaaaaaab\'] 只有存在1个a或者以上就匹配
# 贪婪匹配 与 非贪婪匹配 [语法:量词的后面加?号]
贪婪匹配: 默认向更多次数匹配,底层用的是回溯算法;
非贪婪匹配: 默认向更少次数匹配
在量词的后面加一个?号,就是非贪婪模式,例如:.*? .?? .+? .{m,n}? .*? 用的更多
如果遇到了子这个字,在非贪婪模式下,匹配到第一个就返回
回溯算法:
从左向右进行匹配,一直向后找,直到再也找不到了,回头,拿离右侧最近的那个值
#普通例子:
strvar = "刘能和刘铁锤和刘大棍子12313子"
lst = re.findall("刘.", strvar)
print(lst)
# [\'刘能\', \'刘铁\', \'刘大\']
# 1.贪婪匹配
lst = re.findall("刘.?", strvar) # .? 匹配一个字符,重复0次或1次
print(lst)
# [\'刘能\', \'刘铁\', \'刘大\']
lst = re.findall("刘.+", strvar) # + 重复1次或多次,因为贪婪所有就无限重复匹配一个字符
print(lst)
# [\'刘能和刘铁锤和刘大棍子12313子\']
lst = re.findall("刘.*", strvar) # 重复0次或多次,也是因为贪婪所以重复匹配一个字符
print(lst)
# [\'刘能和刘铁锤和刘大棍子12313子\']
lst = re.findall("刘.*子", strvar)
print(lst)
# [\'刘能和刘铁锤和刘大棍子12313子\']
# strvar1 ="刘123456789123456789121子"
lst = re.findall("刘.{1,20}子", strvar) # 刘和子的中间可以匹配最多20个字符,如果是上面一行的strvar1会输出空列表
print(lst, "<==>")
# [\'刘能和刘铁锤和刘大棍子12313子\'] <==>
# 非贪婪匹配
strvar = "刘能和刘铁锤和刘大棍子12313子"
lst = re.findall("刘.??", strvar) # 因为非贪婪,所有?重复0次或1次就变成匹配0次就符合了
print(lst)
# [\'刘\', \'刘\', \'刘\']
lst = re.findall("刘.+?", strvar) # 因为非贪婪模式+ 重复1次或多次,即重复一次就符合
print(lst)
# [\'刘能\', \'刘铁\', \'刘大\']
lst = re.findall("刘.*?", strvar) # 因为非贪婪,所有*重复0次或多次就变成匹配0次就符合了
print(lst)
# [\'刘\', \'刘\', \'刘\']
# 匹配到第一个子就直接返回
lst = re.findall("刘.*?子", strvar) # 从刘开始到第一个子就结束
print(lst)
# [\'刘能和刘铁锤和刘大棍子\']
lst = re.findall("刘.{1,20}?子", strvar)
# 原来有更大的匹配到了,但是非贪婪选择短的符合匹配的就输出,最多中间匹配20次单个任意字符,20个以上就不符合
print(lst)
# [\'刘能和刘铁锤和刘大棍子\']
三.匹配开头结尾 => [元字符] 边界符号
1.\b
\b 用来匹配边界
\b 退格 backspace 是一个转义字符
一般写正则表达式的时候,字符串的前面加上一个r,让转义字符失效
# word 匹配d 为右边界 d\b 匹配w为左边界\bw 贪婪匹配
lst = re.findall(r".*d\b", "word pwd abc") # d的前面匹配一次或者多次,贪婪算法匹配多次及时到符合的仍然继续匹配知道没有符合的获取最长的那个符合的
print(lst)
# [\'word pwd\']
# 非贪婪匹配
lst = re.findall(r".*?d\b", "word pwd abc") ##d的前面匹配一次或者多次,非贪婪算法匹配多次到最短符合就获取
print(lst)
# [\'word\', \' pwd\'] #注意pwd之前有个空格,也是匹配到的字符
# 优化版:舍掉空格 \S 匹配任意非空白符 ,下面就会将单词之间的空格去掉
lst = re.findall(r"\S*?d\b", "word pwd abc")
print(lst)
# [\'word\', \'pwd\']
# 匹配单词的左边界
lst = re.findall(r"\bw.* ", "word abc") # 在*后面有个空格,就是标识匹配到空格,所有这个匹配到\'word \' 这边也存在贪婪算法
print(lst)
# [\'word \']
2.^ 必须以某个字符开头,后面的字符无所谓
3.$ 必须以某个字符结尾,前面的字符无所谓
如果正则里面包含了^或者$ 意味着要把字符串看成一个整体
strvar = "大哥大嫂大爷"
print(re.findall(\'大.\', strvar))
# [\'大哥\', \'大嫂\', \'大爷\']
print(re.findall(\'^大.\', strvar))
# [\'大哥\']
print(re.findall(\'大.$\', strvar))
# [\'大爷\']
print(re.findall(\'^大.$\', strvar)) # 没有匹配到符合的,所有输出空列表
# []
print(re.findall(\'^大.*?$\', strvar)) # 字符串是一个整体,所有要匹配到结尾的字符
# [\'大哥大嫂大爷\']
print(re.findall(\'^大.*?大$\', strvar))
# [] #因为字符串中有以大开头,但是没有大结尾,所有匹配没有符合的,返回空列表
print(re.findall(\'^大.*?爷$\', strvar))
# [\'大哥大嫂大爷\']
# 把字符串看成一个整体,只要一个结果
print(re.findall(\'^g.*? \', \'giveme 1gfive gay \'))
# [\'giveme \']
print(re.findall(\'five$\', \'aassfive\'))
# [\'five\']
print(re.findall(\'five$\', \'aassfive00\'))
# [] #没有以e结尾的
print(re.findall(\'^giveme$\', \'giveme\'))
# [\'giveme\']
print(re.findall(\'^giveme$\', \'givemeq\'))
# [] #没有符合以g开头以e结尾的
print(re.findall(\'^giv.me$\', \'giveme\'))
# [\'giveme\'] #中间那个.可以为任意字符,以g开头和以e结尾外加字符符合
print(re.findall(\'^giveme$\', \'giveme giveme\'))
# [] #没有符合的
print(re.findall(\'giveme\', \'giveme giveme\')) # 符合两个
# [\'giveme\', \'giveme\'] #没有以什么开头或以什么结尾,只要字符符合就可以符合
print(re.findall("^g.*e", \'giveme 1gfive gay\'))
# [\'giveme 1gfive\'] #注意贪婪算法
print(re.findall("^g.*?e", \'giveme 1gfive gay\'))
# [\'give\'] #非贪婪算法,遇到最短符合的字符串就获取