正则表达式
一.认识正则表达式
# 正则表达式:解决字符串问题的工具
#问题:验证输入的手机号是否合法.
# abc - 不是
# 123 - 不是
# 123456789 -不合法
def is_tel_num(tel_no:str):
if tel_no[0] != '1':
return False
if len(tel_no) != 11:
return False
if tel_no[1] not in '3456789':
return False
return tel_no.isdigit()
from re import fullmatch
def is_tel_num2(tel_no:str):
return fullmatch(r'1[3-9]\d{9}',tel_no) != None
tel = '13388361555'
print(is_tel_num2(tel))
message = '收到回复就234数据,78好看2391金虎sshs34'
from re import findall
all_num = findall(r'\d+',message)
print(all_num)
二.匹配类符号
from re import fullmatch
# 1.re模块
'''
re模块是python用来支持正则表达式的一个模块
re模块中提供了各种和正则相关的函数:fullmatch.search.findall.match.split,sub等
fullmatch(正则表达式,字符串) - 判断整个字符串是否完全符合正则表达式描述的规则.
(不符合的时候返回值为空)
python中提供正则表达式的方式:r'正则表达式'
js中提供正则表达式的方式:/正则表达式/
'''
# 2.匹配类符号 - 一个正则符号表示一类字符
# 匹配类符号在正则中的作用:用来要求字符串中某个位置必须是什么样的字符
# 1)普通符号 - 在正则表达式中表示这个符号本身,对应字符串中的字符的要求就是符号本身
#要求字符串:总共有三个字符,第一个是'a',第二个是'b',第三个'c'
result = fullmatch(r'abc','abc') #<re.Match object; span=(0, 3), match='abc'>
print(result)
result = fullmatch(r'abc','mnd') #None
print(result)
# 2). - 匹配一个任意字符
# 要求字符串:总共有3个字符,第一个是'a',最后一个是'c',中间可以是任何符号
result = fullmatch(r'a.c','a!c') #<re.Match object; span=(0, 3), match='a!c'>
print(result)
result = fullmatch(r'..xy','是sxy')
print(result)
# 3)\d - 匹配一个任意数字
result =fullmatch(r'a\dc','a0c') #中间是数字就行
print(result)
result = fullmatch(r'\d\d\d..','823m是')
print(result)
# 4)\s - 匹配一个任意空白字符
# 空白字符包括: 空格.\n.\t.\r
result = fullmatch(r'a\sb','a b')
print(result)
# 5)\w - 匹配一个数字.字母或者下划线或者中文
result = fullmatch(r'a\wb','a_b')
print(result)
# 6)\大写字母 - 与相应的小写字母的功能相反
'''
\D - 匹配任意一个非数字字符
\S - 匹配任意一个非空白字符
\W -
'''
result =fullmatch(r'\Db','a2b')
print(result) # None
result =fullmatch(r'\Wb','a_b')
print(result) # None
# 7)[字符集] - 匹配字符集中任意一个字符(只匹配一个字符
'''
[多个普通符号] - 例如: [abc12], 在a.b.c.1.2.中任意一个匹配
[包含\开头的特殊符号] - 例如: [mn\d].[m\dn].[\dmn]
[字符1-字符2] - 例如:[a-z],要求是任意一个小写字母
[a-zA-Z], 要求是任意字母
[2-9a-z], 要求是2-9或者小写字母
[\u4e00 -\u9fa5] 要求是任意一个中文
[\u4e00-\u9fa5\dabc]
'''
result = fullmatch(r'1[xyz]2','1x2') #x,y,z中间都行
print(result)
result = fullmatch(r'a[mn\d]b','a9b') #mn和数字都行
print(result)
result = fullmatch(r'a[\u4e00-\u9fa5]b','a是b')
print(result)
# result = fullmatch(r'a['一'-'龥']b','a是b') 会报错
# print(result)
result = fullmatch(r'a[a-z,A-Z]b','a1b') # 这个可以
print(result)
# 8) [^字符集] - 匹配不在字符集中的任意一个字符
result = fullmatch(r'1[^xyz]2','1是2') #x,y,z中间反过来都行
print(result)
三.匹配次数
r'\d\d\d\d\d\d\d'
from re import fullmatch,search
#1. *. - 匹配0次或者多次(任意次数)
'''
a* - a出现任意次数
\d* - 任意多个\d -> 任意多个数字
[abc]* - 任意多个[abc] -> 任意多个(a或者b或者c)
...
'''
result = fullmatch(r'a*b','aaaab')
print(result)
result = fullmatch(r'\d*b','2122b')
print(result)
result = fullmatch(r'[A-Z]*b','AJSDSAIHFSIAb')
print(result)
# 2. + - 匹配1次或者多次(至少一次) 前面那个
result = fullmatch(r'a+b','aaab')
print(result)
# 3. ? - 0次或者1次 前面那个
result = fullmatch(r'-?123','-123')
print(result)
# 4.{}
'''
{N} - N次
{M,N} - M到N次
{M,} - 至少M次
{,N} - 至多N次
'''
result = fullmatch(r'\d{3}abc','621abc') #数字出现三次
print(result)
result = fullmatch(r'\d{3,5}abc','2345abc') #数字出现3-5次
print(result)
# 5.贪婪和非贪婪
# 在匹配次数不确定的时候,匹配被划分为贪婪和非贪婪
'''
匹配次数不确定:*.+.?.{M,N}.{M,}.{,N}
贪婪:在次数不确定的情况下,对应的字符串在不同次数,贪婪取最多次出现的结果:
非贪婪:取最小次数结合
贪婪:*、+、?、{M,N}、{M,}、{,N}
非贪婪:*?、+?、??、{M,N}?、{M,}?、{,N}?
'''
re_str = r'\d+'
result =fullmatch(re_str,'26388')
print(result) #<re.Match object; span=(0, 5), match='26388'>
#search(正则表达式,字母串)第一个满足的字符串
result = search(re_str,'26388是多少') # 有一个相同串就行
print(result) #<re.Match object; span=(0, 5), match='26388'>
result =fullmatch(r'\d+?','26388') #贪婪
print(result)
result =search(r'\d+?','26388') #非贪婪
print(result)
result = search(r'.+b','水电费24557')
print(result)
result = search(r'a.*?b',r'实打实amdbsdaw')
print(result) #<re.Match object; span=(3, 7), match='amdb'>
# '<p>你是好吗</p>' - 4 '<p>你是好吗</p><a>百度</a><p>hello world!</p>'
html = '<body><span>开始!</span><p>你是好吗</p><a>百度</a><p>hello world!</p></body>'
result = search(r'<p>(.*?)</p>', html)
print(result, result.group(1))
result = search(r'a.+?c', '手机端发挥amnc你好c会计核算地方abc')
print(result)
四.分组和分支
from re import fullmatch,search,findall
# 1.分组 - ()
# 分组就是在正则中用括号将正则中的部分内容括起来就形成了一个分组
# 1)整体操作
# 2)重复
# 在正则中:\N可以重复\N所在的位置的前面的第N个分组匹配到的内容(必须是在前面
# 3)捕获
#
# 匹配:两个字母两个数字的结构重复3次,'mn78jh56lm89'
result = fullmatch(r'[a-zA-Z]{2}\d\d[a-zA-Z]{2}\d\d[a-zA-Z]{2}\d\d','mn78jh56lm89')
print(result)
result = fullmatch(r'([a-zA-Z]{2}\d\d){3}','mn78jh56lm89')
print(result)
# 匹配: '23abc23''59abc59' -成功
# '23abc56' - 失败
result = fullmatch(r'(\d\d)abc\1','23abc23')
print(result)
result = fullmatch(r'(\d{3})([a-z]{2})-\2\1=\1{3}','876nm-nm876=876876876')
print(result)
# 根据括号顺序判断分组
result = fullmatch(r'(((\d{2})[A-Z]{3})[a-z]{2})-\2-\1-\3','22AAAaa-22AAA-22AAAaa-22')
print(result)
result = findall(r'\d\d','爱喝酒2空间数据789,迷你那23四等奖00')
print(result) #['78', '23', '00']
# 字母后边的连续两个数字
result = findall(r'[a-z](\d\d)','爱喝酒2空间数据wew789,迷你那asd23四等奖00')
print(result) #['w78', 'd23'] # 加括号后['78', '23']
# 2.分支 - |
# abc后面是两个任意数字或者两个任意的大写字母,'abc34' . 'abcKJ'
result = fullmatch(r'abc(\d\d|[A-Z]{2})','abcMN')
print(result)
result = fullmatch(r'abc\d\d|abc[A-Z]{2}','abcMN')
print(result)
五.检测类和转义符号
# 1.检测类符号
# 检测类符号不是匹配符号,不会要求某个位置必须是什么样的字符,而是检查某个位置是否符合相关要求
# 1)\b - 检测是否单词边界
'''
单词边界 - 凡是可以用来将两个单词区分开的符号,例如:空白字符.标点符号.字符串开头和字符串结尾
'''
from re import fullmatch,search,findall
result = fullmatch(r'[a-z]{3}\b[a-z]{2}','')
print(result) #\b只是检测不会起作用,不满足就会None
result = findall(r'\b\d+','11数据2367skjj,89是2039,按键是否768hsj')
print(result) #['11', '89']
result = findall(r'\d+\b','11数据2367skjj,89是2039,按键是否768hsj')
print(result) #['2039']
# 2)\B - 检测是否非单词边界
# 3)^ - 检测是否是字符串开头([]外面)
# 4)$ - 检测是否是字符串结尾
re_str = r'^\d{3}$'
# 2.转义符号
# 正则中的转义符号是指在本身就剧本特殊功能的符号前加\,让它本身的功能变成普通字符
# 写一个正则匹配一个小数
result = fullmatch(r'\d+\.\d+','1323.45')
print(result)
# '23+78'
result = fullmatch(r'\d\d\+\d\d','23+78')
print(result)
# '(护具)'
result = fullmatch(r'\([\u4e00-\u9fa5]{2}\)','(是你)')
print(result)
# '\dabc'
result = fullmatch(r'\\dabc','\dabc')
print(result)
# 补充: 独立存在有特殊意义的符号,放到[]中特殊功能会直接消失变成一个普通字符+,*,.,?,),(
result = fullmatch(r'[.+?$]ab[.]c','+ab.c')
print(result)
六.Re模块
import re
# 1.常用函数
'''
1)re.fullmatch(正则,字符串) - 判断整个字符串是否能够和正则表达式匹配,如果匹配成功返回匹配对象,否则None
2)re.match(正则,字符串) - 匹配字符串开头
3)re.search(正则,字符串) - 匹配字符串中第一个满足正则的字符串
4)re.findall(正则,字符串) - 获取字符串所有满足正则的字符串,返回值是列表
5)re.finditer(正则,字符串) - 获取字符串所有满足正则的字符串,返回值是迭代器
6)re.split(正则,字符串) - 将字符串中所有满足正则的字符串作为切割点对字符串进行切割,返回值是列表,列表元素是字符串
7)re.sub(正则,字符串1,字符串2) -将字符串2中所有正则的字符串全部替换成字符串1
'''
# 1) re.fullmatch(正则,字符串)
result = re.fullmatch(r'\d{3}','728')
print(result)
# 2)re.match(正则,字符串)
result = re.match(r'\d{3}','728撒大声地')
print(result)
#3)re.search(正则,字符串)
result = re.search(r'\d{3}','牛逼728sadsad')
print(result)
# 4) re.findall(正则,字符串) - 获取字符串中所有满足正则的子串,返回值是列表,列表中的元素是匹配到的字符串
result = re.findall(r'\d{3}','牛逼728sadsa564d,sd45s,asfsa556')
print(result) #['728', '564', '556']
result = re.findall(r'([a-z])(\d{3})','牛逼728sadsa564d,sd45s,asfsa556')
print(result) #[('a', '564'), ('a', '556')]
result = re.findall(r'[a-z]\d{3}','牛逼728sadsa564d,sd45s,asfsa556')
print(result) #['a564', 'a556']
result = re.findall(r'[a-z](\d{3})','牛逼728sadsa564d,sd45s,asfsa556')
print(result) #['564', '556']
# 5)re.finditer(正则,字符串)
result = re.finditer(r'\d{3}','牛逼728sadsa564d,sd45s,asfsa556')
print(list(result))
# 6)re.split(正则,字符串) - 将字符串中所有满足正则的字符串作为切割点对字符串进行切割,返回一个列表,列表中的元素是字符串
result = re.split(r'[abc]','我是你的歌a呵呵哒b嘟嘟嘟c牛马妞妈d阿法撒旦')
print(result) #['我是你的歌', '呵呵哒', '嘟嘟嘟', '牛马妞妈d阿法撒旦']
result = re.split(r'[abc]','我是你的歌a呵呵哒b嘟嘟嘟c牛马妞妈d阿法撒旦',2)
print(result) #['我是你的歌', '呵呵哒', '嘟嘟嘟c牛马妞妈d阿法撒旦']
# 7)re.sub(正则,字符串1,字符串2) - 将字符串1中所有满足正则的子串全部替换成子串2
messge = '我是你的歌a呵呵哒b嘟嘟嘟c牛马妞妈d阿法撒旦a三大b所得税'
# 将a.b.c都替换成+++
result = re.sub(r'[abc]','++',messge)
print(result) #我是你的歌++呵呵哒++嘟嘟嘟++牛马妞妈d阿法撒旦++三大++所得税
result = re.sub(r'\d','0','牛逼728sadsa564d,sd45s,asfsa556')
print(result) #牛逼000sadsa000d,sd00s,asfsa000