regex:正则表达式.匹配规则,是否满足规律.
规则字符串.功能强大,通用性很强.
作用:匹配(就是截取)和或查找符合某些规则的字符串.
1.正则的作用:
一种对数据的匹配.过滤/筛选逻辑的表达式
match:表示从头开始匹配,如果一开始第一个字符没有匹配到,就返回None
如果没有匹配到返回None
记住:所有的正则加上r字符,一定保险
保存有匹配结果的结果对象re.match(r'正则','数据')
取出匹配结果 ---> 结果对象.group()
如果没有成功匹配,返回None,成功:返回匹配的结果对象
match函数的作用:从头开始匹配,如果匹配失败就返回None
search():从头开始搜索,如果能够匹配,返回结果.如果匹配失败,就继续往后搜索并返回匹配结果,如果全部搜索完仍然没有匹配
到,则最终返回None.
比较:match():从头开始匹配,第一次匹配失败就不再往后,直接返回None
search():全文搜索匹配,第一次匹配失败之后,继续往后搜索进行匹配.直到全文搜索完.
import re res = re.match(r'world', 'hello world 123') res1 = re.search(r'world', 'hello world 123') print(res.group()) # 没有匹配到,直接报错 AttributeError: 'NoneType' object has no attribute 'group' print(res1.group()) # world """1. 匹配一个字符(元字符)""" # .点字符: 表示任意一个字符< 换行符除外, 换行,是一个字符,是转义的作用> print(len(' ')) # 长度是1 说明一个字符 print(re.search(r'叶问.', '叶问 ').group()) # 也是没有匹配,直接报错,AttributeError: 'NoneType' object has no attribute 'group' print(re.search(r'叶问.', '叶问kk').group()) # 叶问k # []字符: 表示集合中的任意1个字符,注意格式:[字符],字符不需要加''引号,类似白名单的概念 print(re.search(r'叶问[ABC123]', '叶问B').group()) # [-]: -号和[]结合表示匹配字符的范围,例如:[A-Z] 匹配A字母到Z字母,[a-z]匹配小写字母 # 范围:其实就是ASCII码的范围,例如可以[A-z]:表示A-z,即大小写均可以匹配. print(re.search(r'叶问[A-z]', '叶问z').group()) # [^]:取反,禁止匹配集合中 的字符,类似黑名单. 例如[^数字]表示非数字,就是不要数字的意思,反选的意思. print(re.search(r'叶问[^A-z]', '叶问1').group()) # --------------------------d数字占位符,w字符占位符,s,空白字符占位符-----------------------------> # digit:数字 # d 表示数字0-9,记住:是一个字符,等价于[0-9] # 匹配0-9,记住只能是匹配0-9之间的单个字符 print(re.search(r'叶问[0-9]', '叶问5').group()) print(re.search(r'叶问d', '叶问5').group()) # D 匹配一个 非数字字符<任意>等价于[^0-9] print(re.search(r'叶问[^0-9]', '叶问#').group()) print(re.search(r'叶问D', '叶问J').group()) # space:空白 # s: 空白字符 空格 换行 tab缩进 vf 这些空白制表符,等价于[ vf] print(re.search(r'叶问sd', '叶问 9').group()) print(re.search(r'叶问sssssd', '叶问 vf9').group()) print(re.search(r'叶问', '叶问 ').group()) """ 用来设置单词界限。匹配单词(由字母数字或下划线组成的)的开始或结束(匹配开始时,单词之前不能有w;匹配结束时, 单词之后不能有w)。写在表达式某个字符或字符串之前,表示此字符或字符串之前不能有w对应的字符;写在字符后面, 表示此字符之后不能有w对应的字符。 所以可以只有一个放在字符前面或后面,也可以有2个(表示字符前后都不能有w对应的字符)。 """ # S:禁止匹配一个任意的空白字符 等价于 [^ vf] print(re.search(r'叶问sd', '叶问 9').group()) print(re.search(r'叶问[^ vf]d', '叶问 9').group()) # w: word 匹配一个 任意的 数字,字母,下划线 _ 字符 等价于 [da-zA-Z_] print(re.search(r'叶问w', '叶问j').group()) print(re.search(r'叶问[da-zA-Z_]', '叶问_').group()) # W: 匹配一个任意的非数字,字母,_ 的字符,等价于 [^da-zA-Z_] print(re.search(r'叶问W', '叶问@').group()) # 叶问@ print(re.search(r'叶问[^da-zA-Z_]', '叶问#').group()) """匹配多个字符:需要次数的时候-量词""" # {数字}:表示数量,{3}表示3次 # {n}:表示匹配n次,等价于{n,n} {n,m}:表示至少n次,最多m次 # 至少0次,至多100 --> {0,100} 这时候0可以不写,就是{,100}这种 # 如果是无穷次数,则{,} print(re.search(r'叶问d{,}', '叶问133').group()) # * : 就是0次和无穷次,等价于{,}或者{0,},也可以称之为任意多次 # + : 至少一次,等价于 {1,} # ? : 0次或者1次 等价于{,1}或者{0,1} # 变量命名规则:字母,数字,下划线,不能以数字开头. print(re.search(r'[A-z_]w*', '_abc').group()) print(re.search(r'[A-Za-z_]w*', '_abc').group()) # qq号:第一位不是0, 位数在 5-11 位之间 print(re.search(r'[1-9]d{4,10}', '12345678911222').group()) # 匹配邮箱:w -->就表示一个字母/数字/_ 类型的字符. print(re.search(r'w{4,16}@qq.com', '2604244167@qq.com').group()) print(re.search(r'w{4,16}@qq.com', '2604244167@qq.com.cn').group()) """匹配开始位置和结束位置: ^ $""" # match() 可以不写^ 与 search()结合^ 的作用类似 # 开始位置 r'^xx字符' : 以xx字符开始 # 结束位置 r'xx字符$' : 以xx字符结束 # 开始,结束 r'^xxxxAA字符$' : 以x字符开始,以A字符结束 # ^ 匹配的是开始位置,开始位置:前面没有任何字符了 # $ 匹配结束位置,$后面没有任何字符,只能是结束位置 # 匹配的是一个字符串,不是一个单一的字符. # 限制正则从第一个字符开始匹配,匹配到最后一个字符结束 # 以字母,数字,下划线开始,位数是4-16位,以@qq.com结束的邮箱 print(re.search(r'^w{4,16}.*m$', 'Q604244167$$$$$m').group()) """匹配 分组 匿名分组 """ # | 或者 ,匹配 | 左右两边任何一个表达式 print(re.search(r'^w{4,16}@qq.com$|^w{4,16}@sina.com$', '2604244167@qq.com').group()) # (|) 匹配()中|左右两边的任何一个表达式. 分组的意义:将数据从整体提取出来. 和[]不一样 []匹配单个字符, ()匹配一个字符串 print(re.search(r'^w{4,16}@(qq|sina).com$', '2604244167@sina.com').group()) print(re.search(r'^w{4,16}@(qq|sina).com$', '2604244167@qq.com').group()) # 分组目的:将感兴趣的部分数据从整体中提取出来. # () 使用的时候,结合group(1),就是第一个分组,默认是0号分组,0号分组的默认情况是全部结果 print(re.search(r'^(d{3,4})-(d{6,8})$', '0755-12345678').group(1)) print(re.search(r'^(d{3,4})-(d{6,8})$', '0755-12345678').group(2)) # 创建分组:r'(正则)' # .group()默认是.group(0) 表示0号分组,表示正则的整体匹配结果. # 如果有了() 分组,就写成 .group(1)表示 第一个分组,一个()就是一个分组 data = '郑一峰:274667266@qq.com:683760w:15069065451:19870504' result = re.match(r'(.+):(.+):(.+):(d{11}):(d{8})', data) print(result.group(1, 2, 3, 4, 5)) # ('郑一峰', '274667266@qq.com', '683760w', '15069065451', '19870504') # 匿名分组 """引用 匿名分组 分组: 分组编号 """ # 引用分组 如果在后面的正则需要使用前面的分组数据.把前面匹配到的数据在后续使用的位置继续使用 # r'() 分组编号' 记得在分组编号之前加空格 print(re.search(r'^(d{3,4})-(d{6,8}) 1-2$', '0755-12345678 0755-12345678').group()) # r的效果 print(re.search('^(\d{3,4})-(\d{6,8}) \1-\2$', '010-12345678 010-12345678').group()) """有名分组(命名分组): 原因:(())里面出现(),乱了,无序了,所以这时候使用有名分组,匿名分组这个时候就不好 使用了.不方便使用 应用场景:分组数很多,分组引用会很复杂,修改正则中的分组会导致分组编号发生变化,分组引用就会失效,所以使用有名分组 创建分组: r'(?P<分组别名>正则)' 获取分组:结果对象.group('分组名字'),也可以使用序号 """ print(re.search(r'^(?P<quhao>d{3,4})-(d{6,8}) 1-2$', '0755-12345678 0755-12345678').group('quhao')) print(re.search(r'^(?P<quhao>d{3,4})-(d{6,8}) 1-2$', '0755-12345678 0755-12345678').group(1)) """ 引用有名分组:(?P=分组名字) """ print(re.search(r'^(?P<quhao>d{3,4})-(?P<zuoji>d{6,8}) (?P=quhao)-(?P=zuoji)$', '0755-12345678 0755-12345678').group(2)) """re模块其他高级函数:""" """ search(参数1,参数2):全文搜索,找到第一个就返回,返回值是结果对象 match(参数1,参数2):从头,返回值是结果对象,自带^属性 参数1:正则,参数2:数据 findall():找到所有,返回所有值,且是一个列表格式.从数据中查找指定规则的所有数据,返回值是包含所有结果的列表 sub(参数1,参数2,参数3,count = 参数4):将匹配的结果进行替换. 把参数3中符合参数1规则的数据替换为参数2,替换次数为参数4. 参数2不仅可以是一个字符串数据,还可以是一个函数名,会自动去找函数,并执行,将函数执行的返回值放到参数2的位置. split():按指定规则切割数据 """ def func(obj): data = re.match().group() print(data) return str(int(data) + 1) # re.sub(r's|<?w+>| ','','') """贪婪和非贪婪""" # .: 转义之后才能是.外面的r对.的转义无效,r只对的转义有效 re.search(r'https://.+?.jpg', '') # 找到第一个就返回 re.findall(r'https://.+?.jpg', '') # 找到所有,输出到一个列表 """ 默认贪婪 非贪婪:量词 {} + ? * 这些符号后面再加个?就是非贪婪 相对概念:前提条件,能不能满足整体正则表达式匹配,尽量贪婪, 尽量懒惰 """ print(re.match(r'^(d+)(d{7})$', '12345678').group(1, 2)) # -->分成了2组 print(re.match(r'^(d{3,4}?)(d{5})$', '12345678').group(1, 2)) # ('123', '45678')print(len('\1')) # 2 print(len(r'1')) # 2 说明r的效果了. print(re.findall('\\', '\')) # ['\'] """ r字符:对字符串中的自动加进行转义 r'w' == '\w' 如果需要匹配数据的\,正则需要使用\\ """