正则表达式 re模块

发布时间 2023-06-08 19:51:52作者: Meeeoww

正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑
在python中,如果想使用正则表达式,我们需要借助于re模块

字符组

#字符组中括号内匹配数据都是或的关系,默认匹配顺序是从左至右依次匹配
[0123456789]# 匹配0-9的数字
[0-9]# 匹配0-9的数字
[a-z]  # 匹配a-z之间的任何一个字符
[A-Z]  # 匹配A-Z之间的任何一个字符
[0-9a-xA-X] # 匹配0-9、a-f、A-F

字符

.匹配除换行符以外的任意字符
\d匹配数字 
\w匹配字母或数字或下划线
^匹配字符串的开始
$匹配字符串的结尾
a|b匹配字符a或字符b # a|b|c|d匹配a或者b或者c或者d
()匹配括号内表达式,也表示一个组
[...]匹配中括号字符组内的所有字符
[^...] 取反,匹配中括号以外的所有字符 
\W匹配非数字、字母、下划线
\n匹配换行符
\s匹配任意空格

量词

"""
1. 量词不能单独使用,必须跟在字符后面
2. 量词只会影响左边的一个表达式 (例如ab+ 只会影响b)
3. 量词一定配合表达式使用
4. 没有量词修饰匹配的都是一个字符
正则默认都是贪婪匹配,默认是多次
"""

*   			# 匹配零次或更多次,默认多次
+				# 匹配一次或更多次,默认多次
?				# 匹配零次或一次,默认一次
{n}				# 匹配n次	
{n,}			# 匹配n次或更多次,默认多次
{n,m}			# 匹配n到m次,默认m次

贪婪匹配和非贪婪匹配

正则表达式默认情况都是贪婪匹配

  • 贪婪匹配
    字符串:
        <script>hello</script>
    正则表达式:
        <.*>    
    匹配结果:
        <script>hello</script>
  • 非贪婪匹配
'''取消贪婪匹配,在表达式中加?'''
    字符串:
        <script>hello</script>
    正则表达式:
        <.*?>    
    匹配结果:
        <script>
        </script>

转义符 \

在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的"\n"而不是"换行符"就需要对""进行转义,变成'\'

匹配字符:'\n'
正则:'\\n'  等价于 r'\n'

匹配字符:'\\n'  
正则:'\\\\n ' 等价于 r'\\n'

"""在字符串之前加r,让整个字符串不转义"""

re模块

常用方法

  • findall查找所有符合正则表达式的数据,符合条件的都返回
"""
1. 如果匹配到,返回匹配到的结果,并且是列表形式
2. 匹配不到,返回[],并没有报错
"""
import re#首先导入re
res= re.findall('a','kesain jack aatony')
print(res)   #['a', 'a', 'a', 'a']匹配到就返回匹配到的结果,并且是列表形式

res= re.findall('^a','akesain jack aatony')
print(res)     #['a']

res= re.findall('^a','kesain jack aatony')
print(res)     #[]  #匹配不到,返回[],并没有报错

res= re.findall('^alln$','alln') 精准匹配^和$之间的字符
print(res) #['alln']

res= re.findall('^a$','aaa')
print(res) #[]    #匹配不到,返回[]

res=re.findall('^[1-9]\d{13,16}[0-9x]$','110101198001017032')
print(res)#['110101198001017032']
  • search#查找符合正则条件的字符串,符合条件只返回一个结果
'''
1.如果有匹配结果想查看结果要使用group
2.如果没有匹配到结果就返回none
3.如果没有匹配到还使用了group返回就会报错,此时可以使用try……except捕获异常,或者if……else语句对条件进行判断,根据不同的结果执行不同的代码防止报错

'''
res=re.search('b','kesain jack aatony')
print(res)>>>None #匹配不到,返回none

res=re.search('a','kesain jack aatony')
print(res) #<re.Match object; span=(3, 4), match='a'> 
print(res.group()) #a #想看结果必须使用group取值

res=re.search('b','kesain jack aatony')
try:
    print(res.group())
except Exception:
    print('没有匹配到')#没有匹配到#如果没有匹配到还使用了group返回就会报错,此时可以使用try……except捕获异常防止报错

res=re.search('b','kesain jack aatony')
if res:
	print(res.group())
else:
    print('没有匹配到')#没有匹配到#如果没有匹配到还使用了group返回就会报错,此时还可以使用if……else语句根据条件执行不同的代码来防止报错
  • match#只匹配开头符合正则条件的数据,如果不符合就返回none
'''
1.match默认匹配开头的字符串
2.如果没有匹配到结果就返回none
3.如果有匹配结果想查看结果要使用group
4.如果没有匹配到还使用了group返回就会报错,此时可以使用try……except捕获异常,或者if……else语句对条件进行判断,然后根据不同的结果执行不同的代码防止报错
'''
res =re.match('a','kesain jack aatony')
print(res) #None  #默认匹配开始字母,没有匹配到结果就返回none

res =re.match('k','kesain jack aatony')
print(res)#<re.Match object; span=(0, 1), match='k'>
print(res.group())#k  #有匹配结果想查看结果要使用group

res =re.match('a','kesain jack aatony')
try:
    print(res.group())
except Exception:
    print('没匹配到')#没匹配到

res =re.match('a','kesain jack aatony')
if res:
    print(res.group())
else:
    print('没匹配到') #没匹配到   
  • sub #用于在字符串中使用正则表达式进行替换操作
ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4
  • compile#用于将正则表达式编译成模板
obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123 

无名分组和有名分组

  • 无名分组

无名分组取值按照索引取值,索引从1开始,第一个括号索引为1,第二个括号索引为2,以此类推

search情况下:
res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199812067023')#()为分组
print(res.group()) #110105199812067023

res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199812067023')
print(res.group(1)) #10105199812067# 索引(\d{14}),分组取值是按照索引取值,索引从1开始

res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199812067023')
print(res.group(2)) #023#索引的分组是(\d{2}[0-9x])
findall情况下
'''findall方法,分组优先展示,取消分组优先展示?:'''
res = re.findall("^[1-9]\d{14}(\d{2}[0-9x])?$",'110105199812067023')
print(res)#['023']#优先打印分组
res1 = re.findall("^[1-9]\d{14}(?:\d{2}[0-9x])?$",'110105199812067023')#?:取消分组优先展示
print(res1)#['110105199812067023']
  • 有名分组

固定格式(?P正则)

res = re.search("^[1-9](?P<bibi>\d{14})(\d{2}[0-9x])?$",'110105199812067023')
print(res.group(1)) #10105199812067#虽然有名了但依然可以用无名分组索引方式取值

res = re.search("^[1-9](?P<bibi>\d{14})(\d{2}[0-9x])?$",'110105199812067023')
print(res.group('bibi')) #10105199812067#有名分组按照名取值
import re
with open('a.txt', 'r', encoding='utf-8') as f:
    data = f.read()

name_list = re.findall('<h2>(.*?)</h2>', data)
# print(name_list)

# 地址
address_list = re.findall("<p class='mapIco'>(.*?)</p>", data)
# print(address_list)

# 邮箱
email_list = re.findall("<p class='mailIco'>(.*?)</p>", data)
# print(email_list)

# 电话
phone_list = re.findall("<p class='telIco'>(.*?)</p>", data)



res=zip(name_list, address_list, email_list, phone_list)
# print(list(res))
ret = list(res)
for t in ret:
    print("""
        公司名称:%s
        公司地址:%s
        公司邮箱:%s
        公司电话:%s
    """ % (t[0], t[1], t[2], t[3]))