正则表达式
作用: 在一个大的字符串中查找符合某些特殊规则的小字符串 特点: 可读性差, 但是通用性很强(很多编程语言通用)
单词: regular expression
python中的正则模块: re
一、match匹配
匹配规则: 从头开始匹配, 返回第一个匹配成功的数据
- 导包: import re
- 匹配: 匹配结果 = re.match(正则表达式, 要匹配的大字符串数据)
- 处理数据: 匹配成功: 返回匹配成功的数据
匹配失败: 返回None
示例:
# 1.导包: import re
import re
# 2.匹配: 数据对象名 = re.match(正则表达式,要匹配的大字符串内容)
result = re.match('itheima', 'itheima.com')
# 3.处理数据: 从数据对象中把数据取出来
# 非空即为真(True)
if result:
print('匹配成功:', result.group()) # itheima
else:
print('匹配失败!')
二、search匹配
匹配规则: 在整个大字符串中查找, 返回第一个匹配成功的数据
- 导包: import re
- 匹配: 匹配结果 = re.search(正则表达式, 要匹配的大字符串数据)
- 处理数据: 匹配成功: 返回第一个匹配成功的数据
匹配失败: 返回None
示例:
# 1.导包: import re
import re
# 2.匹配: 数据对象名 = re.search(正则表达式,要匹配的大字符串内容)
result = re.search('itheima', 'www.itheima.com')
# 3.处理数据: 从数据对象中把数据取出来
# 非空即为真(True)
if result:
print('匹配成功:', result.group()) # itheima
else:
print('匹配失败!')
三、findall匹配
匹配规则: 在整个大字符串中查找, 把所有匹配成功的数据放到列表中返回
- 导包: import re
- 匹配: 匹配结果 = re.findall(正则表达式, 要匹配的大字符串数据)
- 处理数据: 匹配成功: 以列表的形式返回匹配到的数据
匹配失败: 返回一个空列表
# 1.导包: import re
import re
# 2.匹配: 数据对象名 = re.findall(正则表达式,要匹配的大字符串内容)
# 注意: findall匹配返回的是列表
result = re.findall('itheima', 'www.itheimaitheima.com')
# 3.处理数据: 打印列表
# 非空即为真(True)
if result:
print('匹配成功:',result) # ['itheima', 'itheima']
else:
print('匹配失败!')
四、匹配单个字符规则
符号 | 表达含义 |
---|---|
. | 表示任意一个字符(除了\n) |
[] | 中括号中任意一个字符 |
\d | 代表任意一个数字(0-9) |
\D | 代表任意一个非数字 |
\s | 代表任意一个空白(包括\n) |
\S | 代表任意一个非空白 |
\w | 代表任意一个正常词(字母, 数字, 汉字, 下划线) |
\W | 代表任意一个非正常词(特殊字符) |
匹配任意1个字符(除了\n) |
注: d: digit s: space w: word
示例
import re
# 定义一个函数用于处理数据
def show(result):
if result:
print('匹配成功:', result.group())
else:
print('匹配失败!')
print('-----------------------------------------------------------')
# . : 任意一个字符(除了\n) 举例:nuima_dsh_666_帅气->nuima_dsh_666_帅气
result = re.match('n.ima_dsh.6.6_.气', 'nuima_dsh_666_帅气')
show(result)
result = re.match('nuima_dsh_666.帅气', 'nuima_dsh_666\n帅气')
show(result) # 匹配失败,因为.不能匹配\n
print('-----------------------------------------------------------')
# []: 中括号中任意一个字符 注意: 中括号里的内容是或者关系
result = re.match('[Nn]uima_dsh_666_帅气', 'nuima_dsh_666_帅气')
show(result)
result = re.match('nuima_dsh_[0-9][0-9][0-9]_帅气', 'nuima_dsh_666_帅气')
show(result)
print('-----------------------------------------------------------')
# \d: 任意一个数字(0-9) \d==[0-9]==[0123456789]
result = re.match('nuima_dsh_\d\d6_帅气', 'nuima_dsh_666_帅气')
show(result)
print('-----------------------------------------------------------')
# \D: 任意一个非数字
result = re.match('nuima_dsh_6\D6_帅气', 'nuima_dsh_666_帅气')
show(result) # 匹配失败,因为\D代表非数字
result = re.match('nui\Da_dsh\D666_\D气', 'nuima_dsh_666_帅气')
show(result)
print('-----------------------------------------------------------')
# \s: 任意一个空白(空格,\t,\n)
result = re.match('nuima_dsh_666\s帅气', 'nuima_dsh_666 帅气')
show(result)
result = re.match('nuima_dsh_666\s帅气', 'nuima_dsh_666\t帅气')
show(result)
result = re.match('nuima_dsh_666\s帅气', 'nuima_dsh_666\n帅气')
show(result)
print('-----------------------------------------------------------')
# \S: 任意一个非空白
result = re.match('n\Sima\Sdsh_666\S\S气', 'nuima_dsh_666_帅气')
show(result)
print('-----------------------------------------------------------')
# \w: 任意一个正常词(字母,数字,下划线,汉字)
result = re.match('nuima\wd\wh_6\w6_\w气', 'nuima_dsh_666_帅气')
show(result)
print('-----------------------------------------------------------')
# \W: 任意一个非正常词(特殊字符)
result = re.match('nuima\Wdsh\W666\W帅气', 'nuima?dsh&666@帅气')
show(result)
五、正则匹配多个字符规则
符号 | 表达含义 |
---|---|
* | 匹配前一个字符出现0次或者无限次 |
+ | 匹配前一个字符出现1次或者无限次 |
? | 匹配前一个字符出现0次或者1次 |
{n} | 匹配前一个字符出现n次 |
{x,y} | 匹配前一个字符出现x到y次 |
import re
# 定义一个函数用于处理数据
def show(result):
if result:
print('匹配成功:', result.group())
else:
print('匹配失败!')
# * : 匹配前一个字符出现0次或者无限次 次数>=0
result = re.match('[A-Z].*', 'nuima_dsh_666_帅气') # 需求:第一个字母大写,后面内容任意
show(result)
result = re.match('t.*o', 'to') # 需求: t和o中间可有可无任意字符
show(result)
result = re.match('张.*三', '张三') # 需求: 张和三中间可有可无任意字符(姓名个数>=2)
show(result)
print('----------------------------------------------')
# + : 匹配前一个字符出现1次或者无限次 次数>=1 需求: t和o中间至少一个任意字符
result = re.match('t.+o', 'to')
show(result) # 匹配失败,因为+要求至少1个
result = re.match('t.+o', 'tbo')
show(result)
result = re.match('t.+o', 'tnuimao')
show(result)
result = re.match('张.+三', '张三') # 需求: 张和三中间至少加一个字(姓名个数>=3)
show(result) # 匹配失败,因为+要求至少1个
print('----------------------------------------------')
# ? : 匹配前一个字符出现0次或者1次 次数== 0 或者 次数 == 1
result = re.match('https?', 'http')
show(result)
result = re.match('https?', 'https')
show(result)
print('----------------------------------------------')
# {x}: 匹配前一个字符出现x次 次数==x
result = re.match('nuima_dsh_[0-9]{3}_帅气', 'nuima_dsh_666_帅气')
show(result)
result = re.match('nuima_dsh_\d{3}_帅气', 'nuima_dsh_666_帅气')
show(result)
result = re.match('[a-zA-Z0-9_]{6}', 'abc_123') # 需求: 密码6位
show(result) # 注意此处有一个小的漏洞,一会儿使用匹配开头和结尾解决
print('----------------------------------------------')
# {x,y}:匹配前一个字符出现x到y次 次数>=x 并且 次数<=y
result = re.match('[a-zA-Z0-9_]{8,10}', 'abc_ABC_123_456') # 需求: 密码是8-10位
show(result) # 注意此处有一个小的漏洞,一会儿使用匹配开头和结尾解决
六、正则匹配开头和结尾
符号 | 表达含义 |
---|---|
^ | 匹配以什么开头 |
$ | 匹配以什么结尾 |
注: ^和$一般都是配合使用, 起到限制作用
import re
# 定义一个函数用于处理数据
def show(result):
if result:
print('匹配成功:', result.group())
else:
print('匹配失败!')
# 需求: 密码6位,多或者少都应该匹配失败
result = re.match('^[a-zA-Z0-9_]{6}$', 'abc_123')
show(result) # 匹配失败,说明^和$起到了限制作用
result = re.match('^[a-zA-Z0-9_]{6}$', 'abc123')
show(result)
七、特殊匹配
注意:如果^放到了[]里面, 表示取反
举例: [^\d] == [\D] == \D
# 定义一个函数用于处理数据
def show(result):
if result:
print('匹配成功:', result.group())
else:
print('匹配失败!')
import re
# 匹配
result = re.match('[^\d].*', 'hello')
# 处理数据
show(result) # 非数字开头,匹配成功
八、正则匹配分组
符号 | 表达含义 |
---|---|
| | 匹配左右任意一个表达式(or) |
() | 小括号中的内容为一组, 默认产生从1开始的编号 |
\n | 根据分组编号n引用对应分组 |
(?P) | 给分组起别名 name |
(?P=name) | 根据分组别名name引用对应的分组 |
import re
# 定义一个函数,用于处理数据
def show(data):
if data:
print('匹配成功:', data.group())
else:
print('匹配失败!')
# | : 匹配左右任意一个表达式 或者
# (): 小括号中内容为一组,默认产生从1开始的编号
# 需求.匹配出163,qq,sina的邮箱地址,且@符号之前有4到20位,举例: hello@163.com
result = re.match('([a-zA-Z0-9_]{4,20})@(163|qq|sina)\.com', 'nuima@qq.com')
show(result)
print(result.group(0)) # 0拿的是所有匹配成功的数据
print(result.group(1)) # 根据分组编号1,拿到对应的分组
print(result.group(2)) # 根据分组编号2,拿到对应的分组
# \n: 根据分组编号n引用对应的分组
result = re.match('<([a-zA-Z1-6]+)>.*</\\1>', '<html>标签内容</html>')
show(result)
# (?P<name>) : 给分组起别名name
# (?P=name) : 根据分组名name引用对应的分组
result = re.match('<(?P<name1>[a-zA-Z1-6]+)>.*</(?P=name1)>', '<html>标签内容</html>')
show(result)
九、贪婪模式和非贪婪模式
符号 | 表达含义 |
---|---|
.* | 默认是贪婪模式(尽可能多的匹配) |
.*? | 加了?代表非贪婪模式(尽可能少的匹配) |
示例
import re
# 定义处理数据的函数
def show(result):
if result:
print('匹配成功:', result.group())
else:
print('匹配失败!')
result = re.findall('t.*o', 'tabcoto123t456oabco') # 需求: t和o中间可有可无任意字符
print(result) # tabcoto123t456oabco
result = re.findall('t.*?o', 'tabcoto123t456oabco') # 需求: t和o中间可有可无任意字符
print(result) # tabco
十、拓展
正则切割
# 字符串切割: 字符串.split(切割字符,切几次)
import re
list1 = 'py_data_64期'.split('_')
print(list1) # ['py', 'data', '64期']
# 正则切割: re.split(切割字符,字符串,切几次)
list2 = re.split('_', 'py_data_64期')
print(list2) # ['py', 'data', '64期']
正则替换
# 字符串的替换: 大字符串.replace(旧子串,新子串)
import re
news = '你TMD哦'.replace('TMD', '***')
print(news)
# 正则的替换: re.sub(旧子串,新子串,大字符串)
news2 = re.sub('TMD', '***', '你TMD哦')
print(news2)
正则修饰符
"""
re.S : 能够让.实现真正的匹配任意字符包含\n
re.I : 匹配过程中忽略大小写
"""
import re
# 定义一个函数,用于处理数据
def show(data):
if data:
print('匹配成功:', data.group())
else:
print('匹配失败!')
# re.S: 能够让.实现真正的匹配任意字符包含\n
result = re.match('nuima_dsh_666.帅气气', 'nuima_dsh_666\n帅气', re.S)
show(result)
# re.I : 匹配过程中忽略大小写
# 需求: 已知验证码Ad2C,使用正则匹配验证码
result = re.match('ad2c', 'Ad2C', re.I)
show(result)