Day16_正则表达式笔记和作业
正则表达式
检测类符号
- \b - 检测是否是单词边界
re_str = r'name\b my'
print(fullmatch(re_str, 'name my'))
"""
单词边界:凡是可以将两个单词分开的符号
都是单词边界,比如:空白字符、标点符号、单词开头和结尾
注意:检测类符号是在匹配成功的情况下看检测类符号所在的位置是否符合要求
"""
re_str = r'\b\d\d\b'
result = findall(re_str, 'shj23结合实际 45 计时开始67,数据,89.计算机109')
print(result)
- \B - 检测是否不是单词边界
re_str = r'\B\d\d\B'
result = findall(re_str, 'shj23结合实际 45 计时开始67,数据,89.计算机90l 78')
print(result)
- ^ - 检测是否是字符串开头
re_str = r'^ab[a-z]\d\d\d'
print(fullmatch(re_str, 'abc334'))
- $ -检测是否是字符串结尾
re_str = r'ab[a-z]\d\d\ds$'
print(fullmatch(re_str, 'abc334s'))
匹配次数
- ‘*’ - 0次或者多次(任意次数)
"""
a* - a出现0次或者多次
\d* - \d出现0次或者多次,每次的一个\d可以是任意一个数字
[abc]* - [abc]出现0次或者多次,每次的[abc]都可以在a、b、c中任意选一个
"""
re_str = r'a\d*b'
print(re.fullmatch(re_str, 'a3b'))
print(re.fullmatch(re_str, 'ab'))
- ‘+’ - 1次或者多次
re_str = r'a\d+b'
print(re.fullmatch(re_str, 'a3b'))
print(re.fullmatch(re_str, 'ab'))
- ‘?’ - 0次或者1次
re_str = r'[+-]?[1-9]\d'
print(re.fullmatch(re_str, '+24'))
print(re.fullmatch(re_str, '-91'))
- ‘{ }’ - 自定义匹配次数
- {N} - 匹配N次
- {M,N} - 匹配M到N次,M和N都可以取到
- {M,} - 匹配最少M次
- {,N} - 匹配最多N次
re_str = r'1a{2,5}2'
print(re.fullmatch(re_str, '1aaaaa2'))
- 贪婪和非贪婪
"""
在匹配次数不确定的时候才有贪婪和非贪婪两种模式
贪婪:在能匹配成功的前提下取匹配次数最多的次数。(默认)
非贪婪:在能匹配成功的前提下取匹配次数最少的次数。(在匹配次数后加?(不能是中文字符?))
"""
re_str = r'a.+?b'
print(re.fullmatch(re_str, 'a少年24b'))
print(re.match(re_str, 'appdgfgfbfbdgrrbfs'))
分支和分组
- 分组 - ( )
"""
用法1:将正则表达式中的一部分作为一个整体,进行整体相关操作,比如控制次数
用法2:重复-使用\M来重复第M个分组中的内容
用法3:捕获
"""
re_str = r'([a-z]{3}\d{2}){3}'
print(fullmatch(re_str, 'amn23abm45mnd78'))
# '22a34a56a43'
re_str = r'(\d{2}a){3}\d{2}'
print(fullmatch(re_str, '22a34a56a43'))
# '34abc34' 、'12sfdd12'
re_str = r'(\d\d)abc\1'
print(fullmatch(re_str, '13abc13'))
re_str = r'(\d{2})=([\u4e00-\u9fa5])=\2=\1'
print(fullmatch(re_str, '12=好=好=12'))
- 分支 - |
"""
正则表达式1|正则表达式2 - 先让正则1和字符串进行匹配,如果成功就成功,如果失败
就和正则2匹配,如果匹配成功结果匹配成功,否则匹配失败。(两个正则中只有要一个可以匹配成功就成功)
"""
# '23abc','MKHabc'
re_str = r'\d{2}|A-Z{3}abc'
- 转义字符
# 在本身具备特殊功能或者特殊意义的符号加\,让其功能或者意义消失,表示一个普通符号
# '23.45'、'90.42'
re_str = r'[1-9]\d\.\d{2}'
print(fullmatch(re_str, '13.34'))
# '2+8'
re_str = r'\d[+]\d'
print(fullmatch(re_str, '2+8'))
# 注意:独立具备特殊功能的符号在[]中功能会自动消失,例如:+、*、?、.、(,)等等
# 本身在中括号中有特殊意义的就要特别注意:^、-、[ ]
re模块
- compile(正则表达式) - 创建一个正则表达式对象
re_object = compile(r'\d{3}')
result = re_object.fullmatch('123')
print(result)
print(fullmatch(r'\d{3}', '123'))
- 匹配类方法
"""
1)fullmatch
fullmatch(正则表达式,字符串)
正则表达式对象.fullmatch(字符串) - 判断整个字符串是否符合正则表达式描述的规则,如果不匹配返回None,如果匹配返回匹配对象
2)match
match(正则表达式,字符串) - 判断字符开头是否符合正则表达式描述的规则,如果不匹配返回None,如果匹配返回匹配对象
"""
-
获取匹配结果
- 匹配对象.group( ) - 获取整个正则表达式匹配的结果
- 匹配对象.group(N) - 获取正则表达式中第N个分组匹配到的结果
-
获取匹配结果在原字符串中的位置
-
匹配对象.span( ) - 获取正则表达式匹配结果所在的位置的下标区间
-
匹配对象.span(N) -获取正则表达式中第N个分组匹配到的下标区间
注意:区间如果为( 2 , 6 ),则对应下标区间为[2 , 5 ]
-
-
获取原字符串
- 匹配对象.string
- 查找类方法
- search( )
"""
search(正则表达式,字符串)
正则表达式对象.search(字符串) - 获取字符串中第一个满足正则表达式的子串,如果没有返回None,如果有返回匹配对象。
"""
result = search(r'\d{3}', 'wedfss3434555fgdgdsgfg')
print(result)
- findall( )
"""
findall(正则表达式,字符串)
正则表达式对象.findall(字符串) - 获取字符串所有满足正则表达式的子串,以列表形式返回,列表中的元素是字符串
"""
str1 = 'shj23哈萨克3894=-37ml899计算机上23,90m7788'
result = findall(r'\d+', str1)
print(result)
result = findall(r'[\u4e00-\u9fa5]\d+', str1)
print(result)
# 如果正则中有分组,findall只提取匹配结果中分组匹配到的内容
result = findall(r'[\u4e00-\u9fa5](\d+)', str1)
print(result)
result = findall(r'\d+-[a-z]+', 'hshs899-mn生死狙击2-mak==-2343-jma')
print(result)
result = findall(r'(\d+)-([a-z]+)', 'hshs899-mn生死狙击2-mak==-2343-jma')
print(result)
- finditer
"""
finditer(正则表达式,字符串)
正则表达式.finditer(字符串) - 获取字符串中所有满足正则表达式的子串,返回的是一个迭代器
"""
result = finditer(r'\d+', 'hshs899-mn生死狙击2-mak==-2343-jma')
print(list(result))
result = finditer(r'\d+', 'hshs899-mn生死狙击2-mak==-2343-jma')
print([x.group() for x in result])
- 切割
"""
split(正则表达式,字符串)
正则表达式对象.split(字符串) - 将字符串中所有满足正则表达式的子串作为切割点对字符串进行切割
"""
str1 = '节省时间27计算机上9sjjsn6计算机0292jsjs就几节课2-==解决'
result = split(r'\d+', str1)
print(result)
str2 = '失敬失敬,啥的看玛法,发的发的的。巅峰对决的,放的放的地方。我都烦得很。王八蛋'
result = split(r'[,。]', str2, 2)
print(result)
- 替换
"""
sub(正则表达式,字符串1,字符串2)
正则表达式对象.sub(字符串1,字符串2) - 将字符串2中所有满足正则表达式的子串都替换成字符串1
"""
result = sub(r'\d+', '+', '我的错9电放费电脑03会计法的0353快递费豆腐54脑的', 3)
print(result)
result = sub(r'傻[bB逼]|fuck|王德发', '*', '傻逼')
print(result)
匹配参数
- 单行和多行匹配
"""
默认是多行匹配。
多行匹配的时候.不能和\n(换行)匹配;
"""
# 多行匹配
print(fullmatch(r'a.b', 'a\nb'))
# 单行匹配
print(fullmatch(r'a.b', 'a\nb', flags=S)) # S是从re模块中导入的
print(fullmatch(r'(?s)a.b', 'a\nb'))
- 忽略大小写
"""
默认不忽略大小写
忽略大小写的时候,大写字母可以和对应的小写字母匹配,小写字母也可以和对应的大写字母匹配
"""
# 忽略大小写
print(fullmatch(r'[a-z]{3}123', 'hSm123', flags=I))
print(fullmatch(r'(?i)[a-z]{3}123', 'hSm123'))
# 单行匹配和忽略大小写同时进行
print(fullmatch(r'[a-z]{3}123', 'hSm123', flags=I | S))
print(fullmatch(r'(?is)[a-z]{3}123', 'hSm123'))
作业:
一、不定项选择题
-
能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括(A B D)
A.r"(?\d{3})?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]\d"
D.r"[(]?\d*[)-]\d" -
能够完全匹配字符串“back”和“back-end”的正则表达式包括(A B C D)
A. r“\w{4}-\w{3}|\w{4}”
B. r“\w{4}|\w{4}-\w{3}”
C.r “\S±\S+|\S+”
D. r“\w*\b-\b\w*|\w*” -
能够完全匹配字符串“go go”和“kitty kitty”,但不能完全匹配“go kitty”的正则表达式包括(A D)
A.r “\b(\w+)\b\s+\1\b”
B. r“\w{2,5}\s*\1”
C. r“(\S+) \s+\1”
D. r“(\S{2,5})\s{1,}\1” -
能够在字符串中匹配“aab”,而不能匹配“aaab”和“aaaab”的正则表达式包括(B C )
A. r“a*?b”
B. r“a{,2}b”
C. r“aa??b”
D. r“aaa??b”
二、编程题
1.用户名匹配
要求: 1.用户名只能包含数字 字母 下划线
2.不能以数字开头
3.⻓度在 6 到 16 位范围内
from re import *
re_username = r'(?i)[a-z_][0-9a-z\d_]{5,15}'
print(fullmatch(re_username, 'Afddfdfss'))
- 密码匹配
要求: 1.不能包含!@#¥%^&*这些特殊符号
2.必须以字母开头
3.⻓度在 6 到 12 位范围内
from re import *
re_password = r'[a-z][^!@#¥%^&*]{5,11}'
print(fullmatch(re_password, 'ArnOdsf中国', flags=I))
- ipv4 格式的 ip 地址匹配
提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
from re import *
ip1 = '13.215.46.45'
result = ip1.split('.', 3)
for x in result:
try:
int1 = int(x)
except TypeEerro:
print('ip地址匹配失败!')
break
if not 0 <= int(x) <= 255:
print('ip地址匹配失败!')
break
else:
print('ip地址匹配成功')
方法二:
用正则方法写
- 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
from re import *
str1 = '-3.14good87nice19bye'
result = findall(r'([+-]?\d+(\.\d+))', str1)
sum_result = sum([eval(x[0]) for x in result])
print(sum_result)
- 验证输入内容只能是汉字
from re import *
re_chinese = r'[\u4e00-\u9fa5]+'
print(fullmatch(re_chinese, '我爱你'))
- 匹配整数或者小数(包括正数和负数)
from re import *
re_num = r'[+-]?([1-9]\d*|0)(\.\d+)?'
print(fullmatch(re_num, '+903'))
- 验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0
from re import *
re_QQ_username = r'[a-z\d_]{6,20}'
username = input('请输入用户名:')
result = fullmatch(re_QQ_username, username, flags=I)
if result == None:
print('用户名格式错误!')
else:
print('用户名格式正确!')
re_QQ_nums = r'[1-9]\d{4,12}'
nums = input('请输入QQ号:')
result = fullmatch(re_QQ_nums, nums)
if result == None:
print('QQ号格式错误!')
else:
print('QQ号格式正确!')
- 拆分长字符串:将一首诗的中的每一句话分别取出来
poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。
from re import *
result = split(r'[,。]', poem, 4)
result.remove('')
print(result)