Day16 正则表达式
-
检测类符号
-
\b - 检测是否是单词边界
-
单词边界: 凡是可以将两个单词区分开的符号都是单词边界
-
比如: 空白字符、标点符号对应的字符、字符串的开头和结尾
-
注意: 检测类符号是在匹配成功的情况下看检测类符号的位置是否符合要求
-
re_str = r'abc \b123' print( fullmatch(re_str, 'abc 123')) #<re.Match object; span=(0, 7), match='abc 123'> re_str = r'\b\d\d\b' result = findall(re_str, 'sij12结束 98 按照形成12, 纠结, 21, 计算12i]98') print(result) #['98', '21', '98']
-
-
\B - 检测是否不是单词边界
-
re_str = r'\B\d\d\B' result = findall(re_str, 'sij12结束 98 按照形成12, 纠结, 21, 计算45i 98') print(result) # ['12', '45']
-
-
^ - 检测是否是字符串开头
-
re_str = r'^\d\d' result = findall(re_str, '561sij12结束 98 45按照形成12, 纠结, 21, 12计算12i 98') print(result) # ['56']
-
-
$ - 检测是否是字符串结尾
-
re_str = r'\d\d$' result = findall(re_str, '56sij12结束 98 456按照形成12, 纠结, 21, 计算12i 98') print(result)
-
-
-
匹配次数
-
‘*’ - 任意次数
-
a* - a出现任意次
-
\d* - \d出现任意次数
-
[abc]* - abc任意一个字符出现任意次数
-
re_str = r'a\d*b' print(fullmatch(re_str, 'ab')) print(fullmatch(re_str, 'a1b')) print(fullmatch(re_str, 'a13b')) print(fullmatch(re_str, 'a1345b'))
-
-
‘+’ - 出现至少一次
-
re_str = r'a\d+b' print(fullmatch(re_str, 'ab')) # None print(fullmatch(re_str, 'a1b')) print(fullmatch(re_str, 'a13b')) print(fullmatch(re_str, 'a1345b'))
-
-
? - 出现至多一次
-
re_str = r'a\d?b' print(fullmatch(re_str, 'ab')) print(fullmatch(re_str, 'a1b')) print(fullmatch(re_str, 'a13b')) # None print(fullmatch(re_str, 'a1345b')) # None
-
-
{}
-
{N} - 匹配N次
-
{M,N} - 匹配M到N次,M和N都可以取到
-
{M, } - 匹配至少M次
-
{,N} - 匹配至多N次
-
re_str = r'1a{2,5}2' print(fullmatch(re_str, '1a2')) # None print(fullmatch(re_str, '1aa2')) print(fullmatch(re_str, '1aaa2')) print(fullmatch(re_str, '1aaaaaa2')) # None
-
-
贪婪和非贪婪
-
在匹配次数不确定的时候才有贪婪和非贪婪两种模式.
-
贪婪: 在能匹配成功的前提下取匹配次数最多的次数. (默认)
-
非贪婪: 在能够匹配成功的前提下取匹配次数最少的次数(在匹配次数后加?)
-
re_str = r'a.+b' print(fullmatch(re_str, 'a扫is建档立卡那种类型等级哦ib')) print(match(re_str, 'asjzixb123basdb拉三等奖')) # 5次 9次 13次 re_str = r'a.+?b' print(fullmatch(re_str, 'a扫is建档立卡那种类型等级哦ib')) print(match(re_str, 'asjdxb123basdb拉三等奖')) # 4次 8次 12次
-
-
-
分组或分支
-
分组 - ()
-
用法1: 将正则表达式中的一部分作为一个整体, 进行整体相关操作, 比如控制次数
-
用法2: 重复-使用\M来重复前面第M个分组中的内容
-
re_str = r'([a-z]{3}\d{2}){3}' result = fullmatch(re_str, 'amn12abm23zsg78') print(result) # '23a23a56a23' re_str = '(\d{2}a){3}\d{2}' print(fullmatch(re_str, '23a23a56a23')) # 34abc 78abc78 re_str = r'(\d\d)abc\1' print(fullmatch(re_str, '45abc45')) print(fullmatch(re_str, '45abc55')) # None print(fullmatch(re_str, '45bc45')) # None re_str = r'(\d{2})=([u4e00-\u9fa5])=\2=\1' print(fullmatch(re_str, '23=啥=啥=23')) re_str = r'(\d{2})=\1=([u4e00-\u9fa5])=\2=\1' print(fullmatch(re_str, '23=23=啥=啥=23'))
-
-
分支 - |
-
正则表达式1|正则表达式2 - 先让正则1和字符进行匹配, 如果成功就成功, 如果失败就和正则2匹配, 都失败才失败
-
# '23abc'、'MKHabc' re_str = r'\d{2}abc|[A-Z]{3}abc' print(fullmatch(re_str, 'IOLabc')) re_str = r'\d{2}|[A-Z]{3}abc' print(fullmatch(re_str, '23')) print(fullmatch(re_str, '23abc')) # None
-
-
转义符号 \
-
让特殊功能的符号的功能消失, 表示一个普通符号
-
# '23.56' '90.01' re_str = r'[1-9]\d.\d{2}' print(fullmatch(re_str, '19637')) re_str = r'[1-9]\d\.\d{2}' print(fullmatch(re_str, '19.37')) # '2+9' re_str = r'\d+\d' print(fullmatch(re_str, '91324237')) print(fullmatch(re_str, '9+7')) # None re_str = r'\d\+\d' print(fullmatch(re_str, '91324237')) # None print(fullmatch(re_str, '9+7'))
-
注意: 独立具备特殊功能的符号在[]中功能也会自动消失, 例如: + * ? . ( [ 等
-
本身在[]中具有特殊意义的就要特别注意: ^
-
-
-
re模块
-
compile(正则表达式) - 创建一个正则表达式对象
-
re_obj = re.compile(r'\d{3}') re_obj.fullmatch('123')
-
-
匹配类方法
-
fullmatch
- fullmatch(正则表达式, 字符串)
- 正则表达式对象.fullmatch(字符串)
- 判断整个字符串是否符合正则表达式规则, 不符合返回None,符合返回匹配对象
-
match
-
match(正则表达式, 字符串)
-
正则表达式对象.match(字符串)
-
判断字符串开头是否符合正则表达式规则, 不符合返回None, 符合返回匹配对象
-
result = match(r'\d{3}', '123阿拉斯加宽带哦-100231sa') result = match(r'(\d{3})-([a-z]{2,5})', '112-mog阿拉斯加宽带哦-100231sa') print(result) #<re.Match object; span=(0, 7), match='112-mog'>
-
-
匹配对象
-
匹配对象.group() - 获取整个正则表达式匹配结果
-
匹配对象.group(N) - 获取正则表达式中第N个分组匹配到的结果
-
print(result.group()) # '112-mog' print(result.group(1)) # '112' print(result.group(2)) # 'mog'
-
-
获取匹配结果在原字符串中的位置
-
匹配对象.span()
-
匹配对象.span(N)
-
print(result.span()) # (0, 7) print(result.span(1)) # (0, 3) print(result.span(2)) # (4, 7)
-
-
获取原字符串
-
匹配对象.string
-
print(result.string) #112-mog阿拉斯加宽带哦-100231sa
-
-
-
查找类方法
-
search
-
search(正则表达式, 字符串)
-
正则表达式对象.search(字符串)
-
获取字符串中第一个满足正则表达式的子串, 如果没有返回None, 否则返回匹配对象
-
result = search(r'\d{3}', 'sjxa12341瞬间xz856sjiaskjdlji--奥术大师多123') print(result) #<re.Match object; span=(4, 7), match='123'>
-
-
findall
-
findall(正则表达式, 字符串)
-
正则表达式.findall(字符串)
-
获取字符串中所有满足正则表达式的子串, 以列表的形式返回
-
str1 = 'shais21233sad32=-213ml25343计算是23, 90毛33' result = findall(r'\d+', str1) print(result) #['21233', '32', '213', '25343', '23', '90', '33'] result = findall(r'[\u4e00-\u9fa5]\d+', str1) print(result) # ['是23', '毛33'] # 如果正则表达式中有分组, findall只提取匹配结果中分组匹配到的内容 result = findall(r'[\u4e00-\u9fa5](\d+)', str1) print(result) # ['23', '33'] result = findall(r'\d+-[a-z]+', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print(result) # ['8982-mn', '2-sasidj', '2323-asd'] result = findall(r'\d+-([a-z]+)', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print(result) # ['mn', 'sasidj', 'asd'] result = findall(r'(\d+)-([a-z]+)', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print(result) # [('8982', 'mn'), ('2', 'sasidj'), ('2323', 'asd')]
-
-
finditer
-
finditer(正则表达式, 字符串)
-
正则表达式对象.finditer(字符串)
-
获取字符串中所有满足正则表达式的子串, 返回值是迭代器,迭代器中元素是匹配对象
-
str1 = 'shais21233sad32=-213ml25343计算是23, 90毛33' result = finditer(r'\d+', str1) print(list(result)) print('-----------------') result = finditer(r'(\d+)-([a-z]+)', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print('所有匹配结果:',[x.group() for x in result]) result = finditer(r'(\d+)-([a-z]+)', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print('匹配的所有数字结果:', [x.group(1) for x in result]) result = finditer(r'(\d+)-([a-z]+)', 'asd8982-mn飒飒的话2-sasidj==-2323-asd=爱上降低') print('匹配的所有字母结果:', [x.group(2) for x in result])
-
-
切割
-
split(正则表达式, 字符串)
-
正则表达式对象.split(字符串)
-
将字符串中所有满足正则表达式的子串作为切割点对字符串进行切割
-
str1 = '撒大苏打123aasda阿瑟东23=qweas123ji1阿斯顿3213' result = split(r'\d+', str1) print(result) # ['撒大苏打', 'aasda阿瑟东', '=qweas', 'ji', '阿斯顿', ''] str2 = '飒飒的, 阿斯顿. 啊实打实的, 斯洛克.按时大撒达娃大撒' result = split(r'[,.]', str2) print(result) # ['飒飒的', '', '阿斯顿', '', '啊实打实的', '', '斯洛克', '按时大撒达娃大撒'] result = split(r'[,.]', str2, 3) print(result) # ['飒飒的', '', '阿斯顿', ' 啊实打实的, 斯洛克.按时大撒达娃大撒']
-
-
替换
-
sub(正则表达式, 字符串1, 字符串2)
-
sub(字符串1, 字符串2)
-
将字符串2中所有满足正则表达式的子串都替换正字符串1
-
result = sub(r'\d+', '+', 'sdo12ajasdh123asi23dj12asd9,98-=-1') print(result) #sdo+ajasdh+asi+dj+asd+,+-=-+ result = sub(r'\d+', '+', 'sdo12ajasdh123asi23dj12asd9,98-=-1', 3) print(result) #sdo+ajasdh+asi+dj12asd9,98-=-1
-
-
-
-
匹配参数
- 匹配参数: 1. 单行匹配 2. 忽略大小写
-
单行匹配和多行匹配
-
默认是多行匹配
-
多行匹配时, '.‘不能和\n(换行)进行匹配; 单行匹配时’.'可以和\n进行匹配
-
# 多行匹配 print(fullmatch(r'a.b', 'a\nb')) # None # 单行匹配 print(fullmatch(r'a.b', 'a\nb', flags=S)) # <re.Match object; span=(0, 3), match='a\nb'> print(fullmatch(r'(?s)a.b', 'a\nb')) # <re.Match object; span=(0, 3), match='a\nb'>
-
-
忽略大小写
-
默认不忽略大小写
-
print(fullmatch(r'[a-z]{3}123', 'hSm123')) # None # 忽略大小写 print(fullmatch(r'[a-z]{3}123', 'hSM123', flags=I)) print(fullmatch(r'(?i)[a-z]{3}123', 'hSM123')) # 单行匹配和忽略大小写同时进行 print(fullmatch(r'abc.123', 'ABC\n123', flags=I|S)) #<re.Match object; span=(0, 7), match='ABC\n123'> print(fullmatch(r'(?si)abc.123', 'ABC\n123')) #<re.Match object; span=(0, 7), match='ABC\n123'>
-
作业
一、不定项选择题
- 能够完全匹配字符串
"(010)-62661617"
和字符串"01062661617"
的正则表达式包括(ABD )
A.r"\(?\d{3}\)?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"
-
能够完全匹配字符串“back”和“back-end”的正则表达式包括( BCD)
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”的正则表达式包括( AD)
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”的正则表达式包括(BD )
A. r“a*?b”
B. r“a{,2}b”
C. r“aa??b”
D. r“aaa??b”
二、编程题
1.用户名匹配
要求: 1.用户名只能包含数字 字母 下划线
2.不能以数字开头
3.⻓度在 6 到 16 位范围内
[^0-9]\w{6,16}
- 密码匹配
要求: 1.不能包含!@#¥%^&*这些特殊符号
2.必须以字母开头
3.⻓度在 6 到 12 位范围内
[a-z]+[^!@#¥%^&*]{5,11}
- ipv4 格式的 ip 地址匹配
提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
r'(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.25[0-5]|2[0-4]\d|[0-1]?\d?\d)\2{3}'
- 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
str1 = input('请输入字符串:')
result = findall(r'((\-|\+)?\d+(\.\d+)?)', str1)
sum1 = sum(eval(x[0]) for x in result)
print(sum1)
-
验证输入内容只能是汉字
str1 = input('请输入:') result = fullmatch(r'[\u4e00-\u9fa5]+', str1) if result == None print('验证失败,输入有误,请输入汉字') else: print('验证成功')
-
匹配整数或者小数(包括正数和负数)
r'((\-|\+)?\d+(\.\d+)?)'
-
验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0name_in = input('请输入用户名:') qq_in = input('请输入qq:') name_result = fullmatch(r'\w{6,20}', name_in) if name_result == None: print('用户名输入有误') else: print('用户名输入成功') qq_result = fullmatch(r'[1-9]\d{4,11}', qq_in) if qq_result == None: print('用户名输入有误') else: print('用户名输入成功')
-
拆分长字符串:将一首诗的中的每一句话分别取出来
poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’
poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
result = split(r'[,。]+', poem)
print(result)