2022.10.13 周四
正则表达式
1.正则表达式
正则表达式是一种可以让复杂的字符串问题变得简单的工具
# 问题:判断手机号是否合法
tel = '15881388789'
if len(tel) != 11:
print('不是合法的手机号')
else:
for x in tel:
if not '0' <= x <= '9':
print('不是合法的手机号')
break
else:
if tel[0] !='1':
print('不是合法的手机号')
elif '3' <= tel[1] <= '9':
print('是合法的手机号')
else:
print('不合法')
# 方法2 正则表达式
tel = '158813887891'
from re import fullmatch
print(fullmatch(r'1[3-9]\d{9}',tel) != None)
2.fullmatch函数
fullmatch(正则表达式,字符串) ——判断字符串和正则表达式是否完全匹配(判断整个字符串是否符合正则表达式所描述的规则)如果不符合返回None
python提供正则表达式的方式:直接将正则表达式作为一个字符串内容(正则需要使用引号引起来,而且引号前面一般需要加r)
3.正则表达式语法
写正则表达式都是通过正则符号来描述字符串规则
1.匹配类符号——用来规定字符(用来描述对字符的要求)
-
普通字符——除了特殊符号以外的符号都是普通字符(在正则中表示符号本身)
-
. ——匹配任意一个字符
-
\d ——匹配任意一个数字字符
-
\s ——匹配任意一个空白字符(’ ‘、’\n’、‘\t’)
-
\w ——匹配任意一个数字、字母、下划线或者中文
-
\D、\S、\W ——匹配任意一个非数字字符、非空白字符、非下划线
-
[字符集] ——匹配字符集中任意一个字符
-
用法1:在[]中提供多个普通字符,匹配多个字符中的任意一个
-
用法2:[字符1**-**字符2]——匹配字符1到字符2范围中的任意一个字符(编码值范围)
-
用法3:在[ ]中包含\开头的特殊符号
[\da-zA-Z_\u4e00-\u9fa5] == \w
注意 [ ]中的减号只有在两个字符之间的时候才表示谁到谁
-
-
[^字符集] ——匹配不在字符集中任意一个字符
- [^A-Z]——匹配任意一个非大写字母
2.匹配次数
任何匹配类符号后面都可以添加匹配次数对应的符号来控制字符的个数
-
+——匹配1次或者多次
-
*——匹配0次或者多次(任意次数)
-
?——匹配0次或者一次
-
{}
- {N}——N次
- {M,N}——M到N次
- {M,}——至少M次
- {,N}——最多N次
-
贪婪和非贪婪
如果匹配次数不确定,匹配的时候分为贪婪和非贪婪两种模式(默认是贪婪模式)
贪婪模式:在多种匹配次数都可以匹配成功的时候,贪婪取最多的次数来进行匹配
非贪婪模式:在多种匹配次数都可以匹配成功的时候,非贪婪取最少的次数来进行匹配(在不确定的匹配次数后面再加一个?)
3.分组和分支
-
分组——()
-
分组就是用()将正则的部分内容括起来表示一个整体
整体控制(将正则中的一部分)
重复(在正则中用\M来重复它前面第M个分组匹配到的结果)
-
捕获(在获取匹配结果的时候可以自动(只有findall具有自动捕获))
-
分支—— |
正则1|正则2|正则3|……
4.检测类符号
先匹配,匹配成功后再来看检测类符号所在的位置是否符合相关要求
- \b ——检测是否是单词边界(单词边界指的是任何可以将两个单词区分开来的符号:空白符号、英文标点符号、字符串开头和字符串结尾)
- ^ ——检测是否是字符串开头
- $ ——检测是否是字符串结尾
5.转义符号——在具有特殊意义的符号前加 ’ \ ’ 让这个有特殊意义的符号变成一个普通符号
补充:除了\开头的特殊符号,其他符号放在[ ]中对应的特殊功能会自动消失
from re import fullmatch
from re import match,findall
# 1.
print(fullmatch(r'abc','abc'))
print(fullmatch(r'a.c','a+c'))
print(fullmatch(r'a\dc','a1c'))
print(fullmatch(r'\d\d\s\d','23 5'))
print(fullmatch(r'a\wa','a_a'))
print(fullmatch(r'a[mn1]b','a1b'))
print(fullmatch(r'a[2-5]b','a4b'))
print(fullmatch(r'abc[\u4e00-\u9fa5]','abc中'))
# 2.
print(fullmatch(r'a+','aaaaa'))
print(fullmatch(r'\d+a','6549848a'))
print(fullmatch(r'a\d{,3}b','a232b'))
# 能匹配成功的字符串:amnb/amnb123b
print(match(r'a.+b','amnb123b中文')) # amnb123b
print(match(r'a.+?b','amnb123b中文')) # amnb
message = '<asd46>爱打架ISA人<asd奥斯卡级><sad659收到><256569-7asf_>'
result = findall(r'<.+?>',message)
print(result)
# 3.
print(fullmatch(r'(\d\d[a-z{3}]){3}','67kmn89jkm78kon'))
# '23mnk23' '89asd89'——匹配成功
print(fullmatch(r'(\d\d)[a-z]{3}\1,'23mnk23'))
print(fullmatch(r'(\d\d)ab([A-Z]{3})-\2','23abMKN-MKN'))
print(fullmatch(r'(\d\d)ab([A-Z]{3})-\2\1','23abMKN-MKN23'))
# 自动捕获案例
message = '<asd46>爱打架ISA人<asd奥斯卡级><sad659收到><256569-7asf_>'
result = findall(r'<(.+?)>',message)
print(result)
message = '阿里山的口红351埃斯库asd3464————=-354萨达265'
result = findall(r'(\d+)元',message)
print(result)
# 4.
message = '23sad6498萨迪胡,564马司法64979 5487,6487阿是689'
print(findall(r'\b\d+\b',message)) # [ 5487,]
message = '23sad6498萨迪胡,564马司法64979 5487,6487阿是689'
print(findall(r'^\d+',message))
print(findall(r'\d+$',message))
# 5.
# 案例:匹配任意一个小数
print(fullmatch(r'\d+\.\d+','23.34'))
print(fullmatch(r'\d\d\+\d\d','23+34'))
4.match, findall, split, search, sub, finditer
fullamatch(正则,字符串) ——完全匹配
findall(正则,字符串) ——匹配字符串开头
split(正则,字符串) ——提取字符串中所有满足正则的子串,返回一个列表
search(正则,字符串) ——匹配字符串中第一个满足正则的字符串
sub(正则,字符串1,字符串2) ——将字符串2中所有满足正则的子串都替换成字符串1
finditer(正则,字符串) ——提取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是匹配对象