Day 12
正则
正则语法
- 正则表达式
正则表达式是一种工具,用来做字符串匹配工作,让字符串处理变得更为方便(但也只能用来处理字符串)
fullmatch(正则表达式,字符串)
# 判断正则表达式和字符串是否完全皮欸,不匹配返回None
-
正则达式语法
-
匹配符号(要求一个符号对应一个字符,影响字符串长度)
1.“普通字符”
表示这个字符本身
2.“ . ”
匹配任意一个字符
3." \d "
匹配任意一个数字字符
4.“ \D ”
匹配任意一个非数字字符
5.“ \s ”
匹配一个空白字符(空格、\n换行、\t制表符)
6.“ \S ”
匹配任意一个非空白字符
7.“ \w ”
匹配任意一个数字、字母、下划线(ASCII表)
8.“ \W ”
匹配任意一个非数字、字母、下划线的ASCII表的字符
9." [字符集] "
匹配字符集中出现的任意一个字符(一个[]只能匹配一个字符)其中,可以用[字符串1-字符串2]表示一个范围内的字符,这个-只有在[]中并且在两个字符之间才有特殊功能;单独存在的具有特殊功能的字符在[]中功能会消失
10." [^ 字符集] "
匹配不在字符集中的任意一个字符,^不在中括号中的开头就没有特殊功能,代表其本身
from re import fullmatch, search re_str1 = r'abc' # 匹配一个字符串,其中有三个字符,分别是a,b,c print(fullmatch(re_str1, 'abc')) # <re.Match object; span=(0, 3), match='abc'> print(fullmatch(re_str1, 'ab')) # None print(fullmatch(re_str1, 'cba')) # None re_str2 = r'.b..c' # 匹配一个长度为5的字符串,第一个字符任意,第二个字符为b,第三四个任意,第五个为c print(fullmatch(re_str2, '4b你,c')) # <re.Match object; span=(0, 5), match='4b你,c'> print(fullmatch(re_str2, '1bac')) # None re_str3 = r'\d\d\d' # 匹配三个任意数字 print(fullmatch(re_str3, '123')) # <re.Match object; span=(0, 3), match='123'> print(fullamtch(re_str3, '12a')) # None re_str4 = r'\d\D\d' # 匹配三个字符,第一个和第三个为任意数字,第二个为任意非数字 print(fullmatch(re_str4, '1d2')) # <re.Match object; span=(0, 3), match='1d2'> print(fullmatch(re_str4, '123')) # None re_sre5 = r'abc\s123' # 匹配七个字符,其中abc和123之间要有空白 print(fullmatch(re_str5, 'abc 123')) # <re.Match object; span=(0, 7), match='abc 123'> print(fullmatch(re_str5, 'abc\n123')) # <re.Match object; span=(0, 7), match='abc\n123'> print(fullmatch(re_str5, 'abc\t123')) # <re.Match object; span=(0, 7), match='abc\t123'> print(fullmatch(re_str5, 'abc_123')) # None re_str6 = r'abc\S\d' # 匹配五个字符分别为'abc'和非空格和任意数字 print(fullmatch(re_str6, 'abc=1')) # <re.Match object; span=(0, 5), match='abc=1'> print(fullmatch(re_str6, 'abc00')) # <re.Match object; span=(0, 5), match='abc00'> print(fullmatch(re_str6, 'abc 0')) # None re_str7 = r'[abc]123' # 匹配'a123','b123','c123'中任意一个 print(fullmatch(re_str7, 'a123')) # <re.Match object; span=(0, 4), match='a123'> print(fullmatch(re_str7, 'k123')) # None re_str8 = r'[\s\d]' # 匹配任意一个空白或数字 re_str9 = r'[1-9abc]' # 匹配1~9中的任意一个数字字符或'a'或'b'或'c' re_str0 = r'[a-zA-Z]' # 匹配任意一个字母 re_str = r'[\da-zA-Z_]' # 匹配数字、字母、下划线,等同于\w re_zh = r'[^\u4e00-\u9fa5]' # 匹配非中文的任意一个字符
-
检测符号(不会匹配字符,也不会影响字符串长度,它在匹配成功的前提下对指定位置的字符进行监测)
1." \b "
监测是否为单词边界(所有能够区分出两个不同单词的符号,例如:空白字符、标点符号、字符串开头和结尾)
2." \B "
监测是否不是单词边界
3." ^ "
监测是否字符串开头
4." $ "
监测是否字符串结尾
- 匹配次数
1." * "
匹配0次或多次(即任意次数)
2." + "
匹配一次或多次
3." ? "
匹配0次或多次
4."{N}","{M,N}","{M,}","{,N}"
匹配N次、匹配M~N次,匹配至少M次,匹配至多N次
# 匹配任意正整数 re_pi = r'[+]?[1-9]\d*' print(fullmatch(re_pi, '89')) # <re.Match object; span=(0, 2), match='89'> # 用户名要求(3~6位字母数字) re_user = r'[\da-zA-Z]{3,6}' print(fullmatch(re_user, '1aer')) # <re.Match object; span=(0, 4), match='1aer'>
- 贪婪和非贪婪模式(在匹配次数不确定时的匹配模式,默认为贪婪模式)
1.贪婪模式
在能匹配成功的前提下,选择匹配次数最多的(+,*,?,{M,N},{M,},{,N})
2.非贪婪模式
在能够匹配成功的前提下,选择匹配次数最少的(在不确定匹配次数的符号后面加?例如:+?,*?,??,{M,N}?,{M,}?,{,N}?)
re_mach = r'a.+b' print(search(re_mach, 'xxamnbpppb==b123')) # <re.Match object; span=(2, 13), match='amnbpppb==b'> re_less = r'a.+?b' print(search(re_less, 'xxamnbpppb==b123')) # <re.Match object; span=(2, 6), match='amnb'>
- 分组
" ( ) "
将要看做一个整体的部分放入()中,就可以将这个()看作一个分组,可以对分组进行操作,其中:1.重复:\M 重复前面第M个分组中的部分;2.捕获:长于re模块中的findall函数使用,findall函数在获取字串时,如果正则中有分组,只会返回分组中满足正则的部分
# 让\d\d[a-z][a-z]出现2~3次 re_turn = r'(\d{2}[a-z]{2}){2,3}' re_repeat = r'1:(\d[a-z]),2:(\d),3:\1\2' print(fullmatch(re_repeat, '1:1a,2:2,3:1a2')) # <re.Match object; span=(0, 14), match='1:1a,2:2,3:1a2'>
- 分支
" | "
类似 if-else;先用第一个正则进行匹配,如果成功,整个正则匹配成功;如果失败,则用第二个正则进行匹配,如此进行匹配
# 写一个正则能够匹配一个字符串:abc后面是3个数字或者是3个大写字母 re_ifel = r'abc(\d{3}|[A-Z]{3})'
- 转义符号
在正则中有特殊意义的符号前加" \ ",让这个符号在正则中的功能消失
-
-
符号对照表
匹配符号 | 作用 |
---|---|
. | 匹配任意一个字符 |
\d | 匹配任意一个数字字符 |
\D | 匹配任意一个非数字字符 |
\s | 匹配一个空白字符(空格、\n换行、\t制表符) |
\S | 匹配一个任意非空白字符 |
\w | 匹配任意一个数字、字母或者下划线(ASCII表) |
\W | 匹配任意一个非数字、字母和下划线的ASCII表字符 |
[ ] | 匹配字符集中出现的任意一个字符 |
[^ ] | 匹配不在字符集中的任意一个字符 |
检测符号 | 作用 |
---|---|
\b | 监测是否是单词边界 |
\B | 监测是否不是单词边界 |
^ | 监测是否字符串开头 |
$ | 监测是否字符串结尾 |
匹配次数 | 作用 |
---|---|
* | 匹配0次或多次(任意次数) |
+ | 匹配一次或多次 |
? | 匹配0次或一次(判断是否存在) |
{N}、{M,N}、{M,}、{,N} | 匹配N次,匹配M~N次,匹配至少M次,匹配最多N次 |
分组和分支 | 作用 |
---|---|
( ) | 将要看作一个整体的部分放入()中,就可以将这个()看作一个分组 |
| | 先用第一个正则进行匹配,如果成功,整个正则匹配成功;如果失败,则用第二个正则进行匹配,如此推进 |
正则模块使用
- 匹配对象
# compile(正则表达式) - 编译正则表达式,返回正则对象
re_obj = re.compile(r'\d{3}')
print(re_obj.fullmatch('123')) # 将正则表达式编译成正则对象后在调用fullmatch时可以直接写字符串
# fullmatch(正则表达式,字符串) - 完全匹配(让整个字符串与正则进行匹配,匹配成功返回匹配对象,失败返回None)
# match(正则表达式,字符串) - 让字符串的开头与正则表达式进行匹配,成功返回匹配对象,失败返回None
print(re.match(r'\d{3}', '231asd')) # <re.Match object; span=(0, 3), match='231'>
print(re.fullmatch(r'\d{3}', '231asd')) # None
-
re模块
- 匹配
匹配对象.group()
其中如果有参数代表获取正则中的第几个分组
- 匹配范围
匹配对象.span() - 左闭右开
其中如果有参数代表第几个分组的下标范围
- 查找
1.search(正则表达式,字符串)
在字符串中查找第一个满足正则的字串,如果找到返回正则对象,否则返回None
2.findall(正则表达式,字符串)
获取字符串中所有满足正则的字串,返回值为字串组成的列表,没有满足的字串返回空列表
3.finditer(正则表达式,字符串)
获取字符串中所有满足正则表达式的字串,返回所有的正则对象
- 切割和替换
split(正则表达式,字符串)
将字符串中满足正则的字串作为切割点
sub(正则表达式,字符串1,字符串2)
将字符串2中满足正则的字串全部替换为字符串1
print(result.group()) # 34knmHK print(result.group(1)) # 34 print(result.group(3)) # HK print(result.group(1, 2)) # ('34', 'knm') print(result.span()) # (0, 7) print(result.span(1)) # (0, 2) print(result.span(3)) # (5, 7) # print(result.span(1, 2)) # 报错:TypeError: span expected at most 1 arguments, got 2 print(re.findall(r'\d{3}', '1234567890')) # ['123', '456', '789'] print(re.findall(r'([a-z\d])\d{3}', 'a123sdf35skd345')) # ['a', 'd'] result = re.finditer(r'([a-z\d])\d{3}', 'a123sdf35skd345') print(result) # <callable_iterator object at 0x0000027A4D7E6FD0> print(list(result)) # [<re.Match object; span=(0, 4), match='a123'>, <re.Match object; span=(11, 15), match='d345'>] print(re.split(r'\d+', 'asd12fsdg354sf456sdg23qve')) # ['asd', 'fsdg', 'sf', 'sdg', 'qve'] print(re.sub(r'\d+', '=', 'asd12fsdg354sf456sdg23qve')) # asd=fsdg=sf=sdg=qve