正则表达式
正则表达式是一种可以让复杂的字符串问题变得简单的工具。
正则不是python特有的语法(不属于python),所有的高级编程语言都支持正则,正则语法通用。
不管通过正则表达式解决的时候是什么问题,写正则的时候都是在使用正则表达式描述字符串规则
python的re模块
re模块是python中用来支持正则表达式的一个模块,模块中包含了所有和正则相关的函数
fullmatch(正则表达式,字符串) - 判断指定的正则表达式和指定的字符串是否完全匹配(判断整个字符串是否符号正则表达式所描述的规则)
如果匹配成功返回匹配对象,匹配失败返回None
from re import *
正则语法 - 匹配类符号
1)普通符号 - 在正则表达式中表示符号本身的符号
result = fullmatch(r'abc', 'abc')
print(result)
2). -匹配任意一个字符(非空格字符)
result = fullmatch(r'a.c', 'awc')
print(result)
result = fullmatch(r'..aaa', '45aaa')
print(result)
3)\d - 匹配任意一个数字字符
result = fullmatch(r'a\dc', 'a1c')
print(result)
4)\s - 匹配任意一个空白字符
空白字符 - 能产生空白效果的字符,例如:空格、换行、水平制表符
result = fullmatch(r'a\sc', 'a\tc')
print(result)
result = fullmatch(r'\d\d\s.ab', '32 dab')
print(result)
5)\D - 匹配任意一个非数字字符
result = fullmatch(r'a\Dc', 'a*c')
print(result)
6)\S - 匹配任意一个非空白字符
result = fullmatch(r'a\Sc', 'asc')
print(result)
7)[字符集] - 匹配字符集中的任意一个字符
[abc] - 匹配a或者b或者c
[abc\d] - 匹配a或b或c或任意一个数字
[1-9] - 匹配1到9的任意一个数字 (获取规则编码值大小)
[a-zA-Z] - 匹配任意一个字母
[a-zA-Z\d_] - 匹配字母数字或者下划线
[\u4e00-\u9fa5] - 匹配任意汉字
注意:[]中减号放在两个字符之间表示谁到谁(确定的方式是根据字符编码值大小确定的),如果减号不在两个字符之间,就表示一个普通的减号。
result = fullmatch(r'a[a-z]b', 'awb')
print(result)
result = fullmatch(r'a[MN12]b', 'a1b')
print(result)
8)[^字符集] - 匹配不在字符集中的任意一个字符
[^MN1-9] 匹配非MN和非1-9的任意一个字符
result = fullmatch(r'a[^MN]b', 'aWb]')
print(result)
result = fullmatch(r'a[^MN1-9]b', 'aWb') #
print(result)
匹配次数问题
1.* - 0次或多次(任意次数)
匹配符号* 注意:*在谁的后面控制的就是谁的次数
a* - 0个或多个a
\d* - 0个或者多个\d
result = fullmatch(r'a*123', 'a123')
print(result)
result = fullmatch(r'a*123', '123')
print(result)
result = fullmatch(r'\d*abc', 'abc')
print(result)
result = fullmatch(r'[MN]*abc', 'NNabc')
print(result)
2)+ - 1次或者多次(至少一次)
result = fullmatch(r'a+123', 'a123')
result = fullmatch(r'a+123', 'aa123')
# 上述匹配都会成功
3)? - 0次或1次
result = fullmatch(r'A?123', '123')
result = fullmatch(r'A?123', 'A123')
4){}
{M,N} - M到N次 至少M次,最大N次
{M,N} - 至少M次
{,N} - 最少0次,最多N次
{N} - N次
result = fullmatch(r'[a-z]{3,5}123', 'axz123')
print(result)
贪婪和非贪婪问题
match(正则表达式,字符串) - 判断字符串开头是否符号正则表达式描述的规则
result = match(r'\d{3}', '234宿舍')
print(result)
# result = match(r'\d{3}', 'p234宿舍') None
1.贪婪和非贪婪
当匹配次数不确定的时候(*,+,?,{M,N},{M,},{,N}),匹配模式分为贪婪和非贪婪两种,默认是贪婪的
贪婪和非贪婪:在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果,非贪婪取最少次数对应的匹配结果(匹配次数不确定的地方,有多种匹配方式都可以匹配成功,贪婪取最多次数)
贪婪模式:,+,?,{M,N},{M,},{,N}(默认是贪婪的)
非贪婪模式:?,+?,??,{M,N}?,{M,}?,{,N}?
1)贪婪模式
result = match(r'a.+b', 'amnnb加算bxxb')
print(result) #amnnb加算bxxb
2)非贪婪模式
result = match(r'a.+?b', 'amnnb加算bxxb')
print(result) #amnnb
注意:如果匹配结果只有一种可能,那么贪婪和非贪婪的结果一样
分支和分组
findanll(正则表达式,字符串) :
1).获取字符串中所有满足正则表达式的字串
2).自动捕获的时候只捕获分组中的内容
3).字串组合成一个列表,如果有多个分组,将每个分组作为元组中每个元素然后将该元组加入列表中作为一个元素
4).例如2个分组,这两个分组作为一个元组,将这个元组加入列表作为一个元素
1.分组 - ()
1)将正则表达式中的一部分作为一个整体进行相关操作
2)重复 - 可以在正则表达式中通过\M 来重复他前面的第M个分组的匹配结果
3)捕获 - 只获取正则表达式中的一部分匹配到的结果 (分为手动捕获,自动捕获两种)
result = fullmatch(r'(\d\d[A-Z]{2})+', '12AS45AS65SD')
print(result)
result = fullmatch(r'(\d\d[A-Z]{2})+', '12AS45AS65SD12')
print(result) # None
# 括号中是一个整体进行匹配字符寻找
result = fullmatch(r'(\d{2})[a-z]\1', '23m23')
print(result)
result = fullmatch(r'(\d{2})[a-z]\1', '23m24')
print(result) # None
# \1 代表第一个分组 重复第一个分组的匹配数字
result = fullmatch(r'(\d{2})([a-z]{3})=\2\1{4}', '23mkl=mkl23232323')
print(result)
# \2 位第二个分组,\1代表第一个分组 {4}重复1分组4次
\M只能重复在他出现之前的分组内容,无法重复在它只会出现的内容
message = '我今年18岁,月薪50000元,身高180,体重70公斤,8块腹肌,每年交300元的腾讯会员费,房贷每月3000元,车贷每月2200元'
result = findall(r'(\d+)元', message)
print(result)
# findall 如果里面有2个分组会是列表中形成一个元组,findall是自动捕获
result = findall(r'今(年)', message)
print(result)
2.分支 - |
正则1|正则2|正则3|… - 匹配可以和多个正则中任意一个正则匹配的字符串
# 匹配一个字符串是三个数字或者两个小写字母
result = fullmatch(r'\d{3}|[a-z]{2}', '234')
print(result)
result = fullmatch(r'\d{3}|[a-z]{2}', 'as')
print(result)
# a23b、amklb
result = fullmatch(r'a\d{3}b|a[a-z]{3}b', 'a234b')
print(result)
result = fullmatch(r'a\d{3}b|a[a-z]{3}b', 'aasdb')
# 如果正则表达式中的一部分实现多选一的效果,变化的部分用分组表示
result = fullmatch(r'a(\d{3}|[a-z]{3})b','aasdb')
print(result)
转义符号
1.转义符号
正则中的转义符号,就是在本身具备特殊功能或者特殊意义的符号前加’',让这个符号变成一个普通符号
# 匹配任意一个小数对应的字符串
result = fullmatch(r'\d+\.\d+', '23.87')
print(result)
.(点)在正则里面表示匹配任意非空格字符,但是我们需要.(点)表示原来得意义就在.前面加反斜杠\
# +234、+7454
result = fullmatch(r'\+\d+', '+23')
print(result)
# (MN),(ASD)
result = fullmatch(r'\([A-Z]+\)', '(AASD)')
print(result)
2.[]里面的转义符号
单独存在有特殊意义的符号(+,*,?,.d等),在[]中特殊意义会自动消失
result = fullmatch(r'\d+[.+*?]\d+', '23.8')
print(result)
result = fullmatch(r'\d+[.+*?]\d+', '23?8')
print(result)
本身在中括号中有特殊功能的符号,如果要表示普通符号加’’
result = fullmatch(r'a[MN-]b', 'a-b') # 代表MN-中任意一个
result = fullmatch(r'a[\^MN]b', 'a^b') # 代表^MN中任意一个
# 也可以把^换到M或者N后面就不用转义字符转义了
检测类标识符
检测类符号是在匹配成功的情况下,检测检测类符号所在的位置是否符合相关要求
检测类字符不会影响匹配结果,只会从筛选结果中判断是否符号标识的要求
1.\b - 检测是否是单词边界
单词边界:可以将2个单词区分开的符号都是单词边界,比如:空白符号、标点符号、英文标点符号、字符串开头和字符串结尾
result = fullmatch(r'abc\b mn', 'abc mn')
print(result)
message = '23m45,89 是4454;2123==90,23 40='
result = findall(r'\d+', message)
print(result)
result = findall(r'\d+\b', message)
print(result)
2.\B - 检测是否不是单词边界
result = findall(r'\B\d+\B', message)
print(result) # ['3', '4', '445', '12']
# 贪婪模式
3.^ - 检测是否是字符串开头
result = findall(r'^\d+', message)
print(result)
result = findall(r'^.{5}', message)
print(result)
# 放在开头才有意义
message = 'l23m45,89 是4454;2123==90,23 40='
result = findall(r'^\d+', message)
print(result) # 该匹配就是空列表
4.$ - 检测是否是字符串结尾
message = '23m45,89 是4454;2123==90,23 40='
result = findall(r'.{5}$', message)
print(result)
# 放在结尾才有意义
re模块相关函数
1.常用函数
1).fullmatch(正则表达式,字符串) - 完全匹配,判断整个字符串是否符号正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空
result = fullmatch(r'\d{3}', '234')
print(result)
2).match(正则表达式,字符串) - 匹配字符串开头,判断字符串开头是否符号正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空
result = match(r'\d{3}', '123数据库')
print(result)
3).search(正则表达式,字符串) -获取字符串中第一个能够和正则匹配成功的字串,能找到返回匹配对象,没找到返回空(字符串中有一个字串就能成功返回第一个字串)
result = search(r'\d{3}', 'ba12345还是')
print(result)
4).findall(正则表达式,字符串) - 或者字符串中所有满足正则的字串,返回一个列表,列表中的元素是字符串。没找到会返回空列表
注意:如果正则表达式中有分组,会针对对分组做自动捕获(只获取分组匹配到的结果)
result = findall(r'\d{3}', 'asd132asd455asd241')
print(result)
5).finditer(正则表达式,字符串) - 获取字符串中所有满足的正则的字串,返回一个迭代器,迭代器中的元素是每个字串对应的匹配结果。没有匹配结果也会返回匹配对象
result = finditer(r'\d{3}', 'asd132asd455asd241')
print(result) # 迭代器
# print(next(result)) # 返回匹配对象
print(list(result)) # 返回匹配对象
6).split(正则表达式,字符串) - 将字符串中所有满足正则的字串作为切割点对字符串进行切割,返回列表
str1 = '123amMKba氨氮大456aLKad99=='
print(str1.split('a')) # 虽然和字符串差不多,但是字符串只能切一个,而正则的切割灵活性更高
# 将str1中的a和b作为切割点对字符串进行切割
result = split(r'a|b', str1)
result = split(r'[ab]', str1)
print(result)
7).sub(正则表达式,字符串1,字符串2) - 将字符串2中所有满足正则的字串都替换成字符串1 返回列表
result = sub(r'\d', '++', 'ba123sdaasd123')
print(result) #ba++++++sdaasd++++++
2.匹配对象
result = fullmatch(r'(\d{3})([A-Z]{2})', '234KM')
print(result)
1)直接获取整个正则表达式对应的匹配结果:匹配对象.group()
print(result.group())
2)手动捕获某个分组对应的匹配结果:匹配对象.group(分组数)
print(result.group(1)) # 234
print(result.group(2)) # km
3)获取匹配结果在原字符串中的位置:匹配对象.span
print(result.span()) # (0,5)
3.参数
1)匹配忽略大小写:(?i)
result = fullmatch(r'(?i)abc', 'aBC')
print(result)
必须放在开头
2)单行匹配:(?s)
多行匹配:匹配的时候.不能和换行(\n)进行匹配,别的都可以
单行匹配:匹配的时候.可以和换行(\n)进行匹配
result = fullmatch(r'(?s)abc.123', 'abc\n123')
print(result) # None
result = fullmatch(r'(?s)abc.123', 'abc\n123')
print(result)