正则表达式

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+>|&nbsp','','')

"""贪婪和非贪婪"""
# .: 转义之后才能是.外面的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'
如果需要匹配数据的\,正则需要使用\\
"""
原文地址:https://www.cnblogs.com/huaibin/p/12107265.html