day16 - 正则表达式
1,匹配符号
1),re模块
"""
re模块是python提供的专门用支持正则表达式的一个模块
fullmatch函数:
fullmatch(正则表达式,字符串) - 让正则表达式和字符串进行完全匹配,如果匹配失败返回None
2,正则语法
"""
正则表达式 - 正则表达式是一个让字符串复杂问题变得简单的工具
写正则表达式的主要工作:用正则符号描述清楚相关字符串的规则
python正则表示方式:r'正则表达式'
js的正则:/正则表达式/
"""
from re import fullmatch
1)普通字符(普通符号)
"""
在正则中除了有特殊功能或者特殊意义以外的符号;
普通字符在正则中表示符号本身。
"""
匹配一个字符串有三个字符分别是a,b,c
re_str = r'abc'
print(fullmatch(re_str,'abc'))
2) . - 匹配一个任意字符
"""
注意:一个. - 只能匹配一个任意字符
"""
匹配一个字符,长度是3,第一个字符是a,最后一个字符是c,a和c之间是任意一个字符
re_str = r'a.c'
print(fullmatch(re_str,'a+c'))
re_str = r'abc...'
print(fullmatch(re_str,'abcm./'))
print(fullmatch(re_str,'abcm\t/'))
3) \d - 匹配任意一个数字字符
"""
"""
re_str = r'a\d\dc'
print(fullmatch(re_str,'a32c'))
4) \s - 匹配任意一个空白字符
"""
空白字符:空格 回车(\n) 制表符(\t)
"""
re_str = r'a\sb'
print(fullmatch(re_str,'a b'))
print(fullmatch(re_str,'a\nb'))
print(fullmatch(re_str,'a b')) #None
*5) \w - 匹配任意一个字母,数字或者下划线(不好用)
6)
"""
\D - 匹配任意一个非数字字符
\S - 匹配任意一个非空白字符
"""
print(fullmatch(r'a\Sb\D','a>b='))
print(fullmatch(r'a\Sb\D','a b=')) #None
7)[字符集] - 匹配字符集中的任意一个字符
"""
注意:一个[]只能匹配一个字符
[多个普通字符] - 例如:[abc],可以匹配a或者b或者c
[包含\开头的特殊符号的字符集] - 例如:[\dabc],可以匹配任意数字或者a或者b或者c
[包含减号在两个字符之间的字符集] - 这个时候的减号表示谁到谁(注意:减号前面的字符的编码必须小于减号后面的)
例如:
[a-b] - 匹配任意一个小写字母
[a-d]
[a-zA-Z],[A-Za-z] - 匹配任意一个字母
[\u4e00-\u9fa5]
[a-z123]
[a-z\d] - 匹配任意一个小写字母或者任意一个数字
"""
re_str = r'a[xym]b'
print(fullmatch(re_str,'axb'))
print(fullmatch(re_str,'ayb'))
print(fullmatch(re_str,'amb'))
re_str = r'a[a\db]b'
print(fullmatch(re_str,'a5b'))
print(fullmatch(re_str,'aab'))
print(fullmatch(re_str,'abb'))
print(fullmatch(r'x[a-zA-Z]y','xmy'))
print(fullmatch(r'x[a-zA-Z]y','xKy'))
print(fullmatch(r'x[a-zA-Z*&]y','x*y'))
8)[^字符集] - 匹配任意一个不在字符集中的任意一个字符
"""
[^abc] - 匹配除了a b c以外的任意一个字符
[^a-z] - 匹配除了小写字母以外的任意一个字符
"""
print(fullmatch(r'a[^\u4e00-\u9fa5]c','a是c')) #None
注意:[]中的-和^只有放在指定位置的时候才有特殊功能,否则在[]中就是一个普通的符号。
2,检测类符号
from re import fullmatch,findall
"""
检测类符号的存在不影响被匹配的字符串长度,它的作用是在匹配成功的前提下检测符号所在的位置是否符合要求
检测类符号的用法:先去掉检测类符号,看是否能匹配成功,如果失败整个正则匹配失败,如果成功再来看检测类符号的位置是否符号要求
"""
1),\b - 检测是否是单词边界
"""
单词边界 - 能够区分两个不同单词的符号都属于单词边界:例如:空白,标点符号,字符串开头或者字符串结尾
and you
"""
re_str = r'abc\b123'
print(fullmatch(re_str,'abc123')) #None
print(fullmatch(re_str,'abc 123')) #None
re_str = r'abc,\b123'
print(fullmatch(re_str,'abc,123'))
findall(正则表达式,字符串) - 获取字符串中所有满足正则表达式的子串
str1 = '12ksksj78ss 34抗生素,89 试试看90 56 江苏省23'
result1 = findall(r'\d\d',str1)
print(result1)
result2 = findall(r'\d\d\b',str1)
print(result2)
result3 = findall(r'\b\d\d\b',str1)
print(result3)
2),\B - 检测是否是非单词边界
result1 = findall(r'\d\d\B',str1)
print(result1)
3),^ - 检测是否是字符串开头
re_str = r'^\d\d'
print(fullmatch(re_str,'12'))
print(findall(r'^\d\d',str1))
4), $ - 检测是否是字符串结尾
/^1[3-9]\d{9}$/
re_str = r'^\d\d$'
print(fullmatch(re_str,'67'))
3,匹配次数
from re import fullmatch,match
import requests
1),* - 表示匹配0次或多次(任意次数)
"""
用法匹配类符号*
a* - 匹配任意多个a
\d* - 匹配任意多个数字字符
"""
print(fullmatch(r'a*b','ab'))
print(fullmatch(r'a*b','aab'))
print(fullmatch(r'a*b','aaaaab'))
print(fullmatch(r'\d*b','2b'))
print(fullmatch(r'[abc]*x','aabcax'))
2), + - 匹配一次或多次(至少一次)
print(fullmatch(r'a+b','b')) #None
print(fullmatch(r'a+b','ab'))
3), ? - 匹配0次或1次
"""
23,90,-23,+23
"""
re_str = r'[-+]?[1-9]\d'
print(fullmatch(re_str,'-12'))
print(fullmatch(r'a?b','b'))
print(fullmatch(r'a?b','ab'))
print(fullmatch(r'a?b','aab'))
4),{}
"""
{N} - 匹配N次
{M,N} - 匹配M到N次
{,N} - 匹配最多N次
{M,} - 匹配至少M次
* == {0,}
+ == {0,1}
? == {0,1}
"""
print(fullmatch(r'\d{4}','2456'))
print(fullmatch(r'\d{3,5}','234'))
print(fullmatch(r'\d{3,5}','2334'))
print(fullmatch(r'\d{3,5}','23445'))
print(fullmatch(r'\d{3,5}','23445354')) #None
print(fullmatch(r'\d{3,5}','24')) #None
print(fullmatch(r'\d{,5}','234'))
print(fullmatch(r'\d{,5}',''))
print(fullmatch(r'\d{,5}','234553454')) #None
print(fullmatch(r'\d{3,}','24')) #None
print(fullmatch(r'\d{3,}','234'))
print(fullmatch(r'\d{3,}','25443654'))
注意:匹配次数对应的符号前面必须是匹配类符号
print(fullmatch(r’+{2,3},’++’)) #None
5),贪婪和非贪婪
"""
在匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种,默认是贪婪模式
*,+,?,{M,N},{,M},{,N} - 贪婪的
在匹配成功的前提下,贪婪是匹配次数选最多的那个次数,非贪婪是匹配次数最少的那个次数。
*?,+?,??,{M,N}?,{M,}?,{,n}? - 非贪婪的
"""
print(match(r'\d{3}','123'))
print(match(r'\d{3}','123sfsafsa'))
print(match(r'\d{3}','we123')) #None
print(match(r'a.*b','adsdsb123'))
print(match(r'a.*b','adbs34bdsb123')) #有三种情况可以成功因为贪婪所以最后匹配次数最多的情况
print(match(r'a.*b','adbs34bdsb123'))
print(match(r'a.*?b','adbs34bdsb123')) #<re.Match object; span=(0, 3), match='adb'>
5,分组和分支
from re import fullmatch
1),() - 分组
"""
作用1:将()中的内容作为一个整体,进行整体相关操作,例如,整体控制次数
作用2:通过’\M‘重复前面第M个分组匹配到的结果,M从1开始
作用3:捕获(在findall中讲)
"""
str1 = '78nj34ne10rj'
print(fullmatch(r'\d\d[a-z]{2}\a\a[a-z]{2}\a\a[a-z]{2}',str1))
print(fullmatch(r'(\d\d[a-z{2}]){3}',str1))
str1 = r'abababab'
print(fullmatch(r'(ab)+',str1))
str1 = '23abc23'
print(fullmatch(r'(\d{2})abc\1','23abc23'))
print(fullmatch(r'(\d{2})abc\1','23abc24')) #None
print(fullmatch(r'(\d{3})([a-z]{3})-\2','234abc-abc'))
print(fullmatch(r'(\d{3})([a-z]{3})-\1','234abc-234'))
print(fullmatch(r'(\d{3})([a-z]{3})-\2\1','234abc-abc234'))
print(fullmatch(r'(\d{3})([a-z]{3})-\1{2}','234abc-234234'))
2),| - 分支
"""
正则1|正则2 - 先用正则1进行匹配。如果成功就直接匹配成功,如果匹配失败再用正则2进行匹配
"""
要求能同时匹配’abc98‘和’abcMKP’
print(fullmatch(r'abc\d{2}|abc[A-Z]{3}','abcMKP'))
print(fullmatch(r'abc(\d{2}|[A-Z]{3})','abcMKP'))
3),转义符号在特殊符号前加,让符号的功能消失,变成一个普通符号
'+723'
print(fullmatch(r'\+\d{3}','+723'))
print(fullmatch(r'\[\d{3}\]','[234]'))
print(fullmatch(r'\\dabc','\dabc'))
如果是独立存在有特殊功能的符号,将符号放入[]中其功能也会自动消失
print(fullmatch(r'[+*?|()^$]abc',')abc'))
print(fullmatch(r'[\^abc\-z\]]123',']123'))
6,re模块
import re
"""
compile(正则表达式) - 编译正则表达式,返回一个正则表达式对象
fullmatch(正则表达式,字符串)
正则表达式对象.fullmatch(字符串)
"""
re_obj = re.compile(r'\d{3}')
print(re_obj.fullmatch('234'))
print(re.fullmatch(r'\d{3}','234'))
"""
2,fullmatch(正则表达式,字符串) - 让正则表达式和整个字符串进行匹配(完全匹配),匹配失败返回None,匹配成功返回匹配对象
match(正则表达式,字符串) - 匹配字符串开头(判断字符串的开头是否符合正则的规则),匹配失败返回None,匹配成功返回匹配对象
"""
result = re.fullmatch(r'\d{3}','234')
print(result) #<re.Match object; span=(0, 3), match='234'> = 匹配对象
1)获取匹配到的字符串
"""
匹配对象.group() / 匹配对象.group(0) - 获取整个正则匹配到的结果
匹配对象.group(N) - 获取第N个分组匹配到的结果
"""
print(result.group())
result = re.fullmatch(r'(\d{3})-([A-Z]+)','234-K')
print(result.group(2)) #K
print(result.group(1)) #234
2)获取匹配结果在原字符串中的位置信息
"""
匹配对象.span() - 返回的是一个元组,元组中的元素是开始下标和结束下标,结束下标对应的位置取不到
"""
print(result.span())
3)search(正则表达式,字符串) - 获取字符串中第一个满足正则表达式的子串,返回结果是None或者匹配对象
result = re.search(r'\d{3}','f234r,ewe3234')
print(result)
print(result.group())
4),findall(正则表达式,字符串) - 获取字符串中所有满足正则的子串,返回的是列表,列表中的元素是子串(没有分组的时候)
如果正则中只有一个分组,返回列表中的元素是每个分组匹配到的结果
如果正则中有两个或两个以上的分组,返回的列表中的元素是元组,元组中的元组是每个分组匹配到的结果
result = re.findall(r'\d{2}','23wds334de54,43ere,33434rr')
print(result) #['23', '33', '54', '43', '33', '43']
result = re.findall(r'(\d{2})\D','23wds334de54,43ere,33434rr')
print(result)
result = re.findall(r'(\d[a-z]){2}','23wds334de54,43ere,33434rr')
print(result)
result = re.findall(r'(\d{2})-([a-z]{3})','23wds-334de54,43-ere,3343-4rr')
print(result)
5),finditer(正则表达式,字符串) - 获取字符串中所有满足正则得到子串,返回的是一个迭代器,迭代器是匹配对象
result = re.finditer(r'(\d{2})-([a-z]{3})','23wds-334de54,43-ere,3343-4rr')
print(result)
r1 = next(result)
print(r1,r1.group(),r1.group(1),r1.group(2))
6),split(正则表达式,字符串) - 将字符串中所有满足正则表达式的子串作为切割点,对字符串进行切割
"""
re.split(正则表达式,字符串,N) - 将字符串中前N个满足正则表达式的子串作为切割点,对字符串进行切割
"""
result = re.split(r'\d','是是5s撒谎9w发福克3斯的7反馈')
print(result)
7),sub(正则表达式,字符串1,字符串2) - 将字符串2中所有满足正则表达式的子串替换成字符串1
sub(正则表达式,字符串1,字符串2,N) - 将字符串2中前N个满足正则表达式的子串替换成字符串1
result = re.sub(r'\d+','*','是是5s撒谎9w发福克3斯的7反馈')
print(result)
message = 'fuck you!打团了,你TM的没看见吗?'
result = re.sub(r'fuck|TM','*',message)
print(result)
message = 'f u c k you!打团了,你TM的没看见吗?'
result = re.sub(r'(f\s*u\s*c\s*k)|TM','*',message)
print(result)
result = re.sub(r'([fF]\s*[uU]\s*[cC]\s*[kK])|TM','*',message)
print(result)
message = 'f u c k you!打团了,你TM的没看见吗?SB'
result = re.sub(r'(?i)(f\s*u\s*c\s*k)|TM|sb','*',message)
print(result)
re_str = open('bad',encoding='utf-8').read()
re_str = r'(?i)%s' % re_str
result = re.sub(re_str,'*',message)
print(result)
8),flags参数
"""
上面的每一个函数都有一个参数flags,用来设置正则参数
1)单行匹配和多行匹配参数
re.S/re.M(默认的)
单行匹配:可以匹配\n
多行匹配;.不能和\n匹配
flags = re.S == r'(?s)正则表达式'
2)忽略大小写:re.I
flags = re.I == r'(?i)正则表达式'
flags = re.S|re.I == r'(?is)正则表达式'
"""
print(re.fullmatch(r'a.b','a\nb',flags=re.M)) #None
print(re.fullmatch(r'a.b','a\nb',flags=re.S)) #<re.Match object; span=(0, 3), match='a\nb'>
print(re.fullmatch(r'(?i)a.c','a\nc'))
print('---------------------------')
print(re.fullmatch(r'abc','abc'))
print(re.fullmatch(r'abc','Abc')) #None
print(re.fullmatch(r'abc','Abc',flags=re.I)) #<re.Match object; span=(0, 3), match='Abc'>
print(re.fullmatch(r'(?i)abc','aBc'))
print(re.fullmatch(r'a.b','A\nb',flags=re.S|re.I))
print(re.fullmatch(r'(?is)a.b','A\nb'))