正则表达式
1、简介
概述
正确的, 符合特定规则的 字符串. 英文名叫: Regular Expression, 简称叫: re, RegExp
作用
主要是校验数据
细节
-
学正则, 主要是学正则的规则. 即: 哪个符号表示什么含义.
-
关于正则, 要求很简单, 只要能用规则, 看懂别人写的式子, 且能简单修改即可, 大部分情况下无需你手动编写.
-
到目前为止, 正则已经经历了N长的时间, 几乎你遇到的绝大多数的正则校验, 前辈们都已经写过了(帮我们写好了).
-
正则不独属于Python, 例如: Java, C#, JavaScript, Go…等众多的语言都支持, 且: 正则的规则都是一样的.
调用过程
-
导包
- import re
-
正则匹配校验.
- result = re.match(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤…) 全词匹配, 从左往右依次匹配
- result = re.search(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤…) 分段批次, 任意一段能匹配即可.
- result = re.compile(…).sub(…) 用于做替换的
-
获取匹配到的数据.
- result.group()
2、几种常用方法
(一)、match
格式
result = re.match(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤…)
全词匹配, 从左往右依次匹配
例如
# 导包
import re# 校验字符串是否是 任意字符 + it + 任意字符.
result = re.match('.it.', 'aitb') # 可以匹配
result = re.match('.it.', 'ait\n') # 未匹配
result = re.match('.it.', 'ait') # 未匹配# 获取到匹配的结果.
if result:# 走这里, 有值, 获取到匹配的数据, 打印即可.print(result.group())
else:# 走这里, 没有匹配到数据, 打印即可.print('未匹配到!')
(二)、search
格式
result = re.search(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤…)
分段批次, 任意一段能匹配即可
例如
# 演示 match 和 search的区别
# 相同点: 都可以做正则校验, 传参都是一样的.
# 不同点: match()是全词匹配, 即: 从左往右依次匹配(不能跳). search()是分段匹配, 有任意一部分能匹配即可.# 判断字符串中是否有 it + 任意的多个字符
# result = re.match('it.*', 'itabc123!@#')
# result = re.match('it.*', 'itabc')
# result = re.match('it.*', 'it')
# result = re.match('it.*', 'aA12!@#itabc') # 未匹配result = re.search('it.*', 'itabc123!@#')
result = re.search('it.*', 'itabc')
result = re.search('it.*', 'it')
result = re.search('it.*', 'aA12!@#itabc') # itabc# 打印匹配到的结果.
if result:# 走这里, 有值, 获取到匹配的数据, 打印即可.print(result.group())
else:# 走这里, 没有匹配到数据, 打印即可.print('未匹配到!')
(三)、compile…sub…
格式
re.compile(正则规则).sub(新字符串, 旧字符串)
去旧字符串中, 找到符合正则规则的内容, 用新字符串来替换.
语法糖
re.sub(正则规则, 新字符串, 旧字符串)
去旧字符串中, 找到符合正则规则的内容, 用新字符串来替换.
例如
import reif __name__ == '__main__':# 案例1: 把下述的符合正则规则的内容, 用*来替换.# 1. 定义 旧字符串.old_str = '你可以这样: 桀1桀2桀, 哈3哈, 呵A呵, 嘿嘿, 嘻嘻, 略略略, 嘤嘤嘤...'# 2. 定义 正则规则(字符串形式)reg_exp = '桀|哈|呵|嘿|嘻'# 3. 把符合正则规则的内容, 用*来替换.# 分解版写法.# 3.1 获取正则对象.# re_obj = re.compile(reg_exp)# 3.2 具体的替换过程.# result = re_obj.sub('*', old_str)# 合并版写法, 正则规则 新内容 旧内容# result = re.compile(reg_exp).sub('*', old_str)# 上述格式的语法糖, 正则规则 新内容 旧内容result = re.sub(reg_exp, '*', old_str)# 4 打印结果print(result)print('-' * 21)# 案例2: 回顾字符串的replace()函数.s1 = '抽烟只抽煊赫门, 一生只爱一个人. 其他烟: 中华, 煊赫门, 天叶, 煊赫门...'# result = s1.replace('煊赫门', '*') # 不写次数, 默认替换所有.# result = s1.replace('煊赫门', '*', 1) # 只替换1次(个)result = s1.replace('煊赫门|中华|天叶', '*')print(f'result: {result}')
3、校验单个字符
规则
. 代表: 任意的1个字符, \n除外
\. 代表: 1个普通的. 即: 取消.的特殊含义
a 代表: 1个字符a
[abc] 代表: a, b, c中任意的1个字符, 即: 要么a, 要么b, 要么c
[^abc] 代表: 除了a,b,c外, 任意的1个字符
\d 代表: 任意的1个整数, 等价于 [0-9]
\D 代表: 任意的1个非整数, 等价于 [^0-9]
\w 代表: 非特殊字符, 即: 大小写英文字符, 数字, _, 汉字
\W 代表: 特殊字符, 即: \w 取反.
\s 代表: 空白字符, 例如: 空格, \t...
\S 代表: 非空白字符, 即: \s取反.
例如
# 导包
import re# 在main中测试
if __name__ == '__main__':# 演示: . 代表: 任意的1个字符, \n除外result = re.match('it.', 'ita') # itaresult = re.match('it.', 'it\t') # it\tresult = re.match('it.', 'it\n') # 未匹配# 演示: \. 代表: 1个普通的. 即: 取消.的特殊含义# 细节: 为了防止打印异常信息, 你可以写成: r'it\.' 或者 'it\\.'result = re.match('it\\.', 'ita') # 未匹配result = re.match('it\\.', 'it.') # it.result = re.match('it\\.', 'it.abc') # it.# 演示: a 代表: 1个字符aresult = re.match('a', 'abc') # aresult = re.match('a', 'xyz') # 未匹配# 演示: [abc] 代表: a, b, c中任意的1个字符, 即: 要么a, 要么b, 要么cresult = re.match('it[abc]', 'itabc') # itaresult = re.match('it[abc]', 'itbc') # itbresult = re.match('it[abc]', 'itd') # 未匹配# 演示: [^abc] 代表: 除了a,b,c外, 任意的1个字符result = re.match('it[^abc]', 'itabc') # 未匹配result = re.match('it[^abc]', 'itbc') # 未匹配result = re.match('it[^abc]', 'itd') # itd# 演示: \d 代表: 任意的1个整数, 等价于 [0-9]result = re.match('ho[0-9]', 'ho1') # ho1result = re.match('ho[0-9]', 'ho3a') # ho3result = re.match(r'ho\d', 'ho3a') # ho3result = re.match(r'ho\d', 'hoa') # 未匹配# 演示: \D 代表: 任意的1个非整数, 等价于 [^0-9]result = re.match(r'ho\D', 'hoa') # hoaresult = re.match(r'ho\D', 'ho3a') # 未匹配# 演示: \w 代表: 非特殊字符, 即: 大小写英文字符, 数字, _, 汉字result = re.match(r'ho\w', 'hoa') # hoaresult = re.match(r'ho\w', 'hoB') # hoBresult = re.match(r'ho\w', 'ho1') # ho1result = re.match(r'ho\w', 'ho_') # ho_result = re.match(r'ho\w', 'ho!') # 未匹配# 演示: \W 代表: 特殊字符, 即: \w 取反.result = re.match(r'ho\W', 'ho!') # ho!result = re.match(r'ho\W', 'ho_') # 未匹配# 演示: \s 代表: 空白字符, 例如: 空格, \t...result = re.match(r'ho\s', 'ho') # 未匹配result = re.match(r'ho\s', 'ho ') # horesult = re.match(r'ho\s', 'ho\t') # horesult = re.match(r'ho\s', 'ho\n') # ho\nresult = re.match(r'ho\s', 'hoa') # 未匹配# 演示: \S 代表: 非空白字符, 即: \s取反.result = re.match(r'ho\S', 'ho') # 未匹配result = re.match(r'ho\S', 'ho ') # 未匹配result = re.match(r'ho\S', 'ho\t') # 未匹配result = re.match(r'ho\S', 'ho\n') # 未匹配result = re.match(r'ho\S', 'hoa') # hoa# 打印校验到的数据.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')
4、校验多个字符
规则
? 代表: 前边的内容, 出现0次 或者 1次
* 代表: 前边的内容, 至少出现0次, 至多出现n次(无数次)
+ 代表: 前边的内容, 出现1次 或者 多次.
a{n} 代表: a恰好出现n次, 多一次少一次都不行.
a{n,} 代表: a至少出现n次, 至多无所谓.
a{n,m} 代表: a至少出现n次, 至多出现m次, 包括n 和 m
例如
# 导包
import re# main中测试
if __name__ == '__main__':# 演示: ? 代表: 前边的内容, 出现0次 或者 1次result = re.match('it.?', 'it')result = re.match('it.?', 'it ')result = re.match('it.?', 'itabcABC')result = re.match('it.?', 'it\nABC') # it# 演示: * 代表: 前边的内容, 至少出现0次, 至多出现n次(无数次)result = re.match('it[abc]*', 'it\nABC') # itresult = re.match('it[abc]*', 'itabcABC') # itabcresult = re.match('it[abc]*', 'it ') # itresult = re.match('it[abc]*', 'it') # it# 演示: + 代表: 前边的内容, 出现1次 或者 多次.result = re.match('it[abc]+', 'it') # 未匹配result = re.match('it[abc]+', 'it ') # 未匹配result = re.match('it[abc]+', 'it\nABC') # 未匹配result = re.match('it[abc]+', 'itabcABC') # itabc# 演示: a{n} 代表: a恰好出现n次, 多一次少一次都不行.result = re.match('it[abc]{2}', 'itabcABC') # itabresult = re.match('it[abc]{2}', 'itacb') # itacresult = re.match('it[abc]{2}', 'ita') # 未匹配# 演示: a{n,} 代表: a至少出现n次, 至多无所谓.result = re.match('it[abc]{2,}', 'ita') # 未匹配result = re.match('it[abc]{2,}', 'itacb') # itacbresult = re.match('it[abc]{2,}', 'itabcABC') # itabc# 演示: a{n,m} 代表: a至少出现n次, 至多出现m次, 包括n 和 mresult = re.match('it[abc]{2,3}', 'itabcde') # itabcresult = re.match('it[abc]{2,3}', 'ita') # 未匹配# 打印结果.print(f'匹配到: {result.group()}' if result else '未匹配!')
5、校验开头和结尾
规则
^ 代表: 正则表达式的 开头
$ 代表: 正则表达式的 结尾
例如
import reif __name__ == '__main__':# 演示: ^ 代表: 正则表达式的 开头# 需求: 校验字符串必须以 it 开头.result = re.match(r'it\d', 'it123') # it1result = re.match(r'it\d', '1it123') # 未匹配!result = re.search(r'it\d', 'it123') # it1result = re.search(r'it\d', '1it123') # it1# ^代表开头, 即: 如下的代码其实是 全词匹配, 必须从字符串的第1个字符开始校验.result = re.search(r'^it\d', '1it123') # 未匹配!# 演示: $ 代表: 正则表达式的 结尾# 需求: 校验字符串必须以 数字 结尾.result = re.match(r'it\d', 'it123a') # it1result = re.match(r'it\d$', 'it123a') # 未匹配!# 扩展: 校验手机号.# 规则: 1. 必须以1开头. 2.第2位数字可以是3 ~ 9. 3.必须是纯数字. 4.长度必须是11位.result = re.match(r'^1[3-9]\d{9}$', '13112345678a')result = re.match(r'^1[3-9]\d{9}$', '13112345678')# 打印匹配到的结果.print(result.group() if result else '未匹配!')
6、校验分组
规则
| 代表: 或者的意思.
() 代表: 分组
\num 代表: 获取第num组的内容
(?P<分组名>) 设置分组名
(?P=分组名) 获取指定分组的内容
细节
正则默认属于第0组, 之后就按照 左小括号来数, 是第几个, 就是第几组.
例如
# | 或的意思
import reif __name__ == '__main__':# 需求: 匹配出 163, 126, qq等邮箱.# 邮箱规则: 前边是4 ~ 20位的字母, 数字, 下划线 + @标记符 + 域名# 1. 定义邮箱字符串.email_str = 'zhangsan@163com'email_str = 'zhangsan@1634.com'email_str = 'zh@qq.com'email_str = 'zhangsan@163.com'# 2. 定义 校验邮箱的 正则表达式.pattern = r'^[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com$'# 3. 校验邮箱.result = re.match(pattern, email_str)# 4. 打印结果.if result:print(f'匹配到: {result.group()}') # zhangsan@163.com, 等价于 result.group(0), 即: 获取所有匹配到的数据print(f'匹配到: {result.group(0)}') # zhangsan@163.com, 效果同上.print(f'匹配到: {result.group(1)}') # 163else:print('未匹配!')# () 分组的意思
import reif __name__ == '__main__':# 需求: 匹配 qq:qq号 这样的数据, 提取出 qq文字 和 qq号码.# 1. 定义字符串.s1 = "qq:1234567"# 2. 匹配数据.result = re.match(r'(qq):(\d{6,11})', s1)# 3. 打印匹配到的数据.if result:print(f'匹配到: {result.group()}') # qq:1234567print(f'匹配到: {result.group(0)}') # qq:1234567print(f'匹配到: {result.group(1)}') # qqprint(f'匹配到: {result.group(2)}') # 1234567else:print('未匹配!')# \num 获取第几组的内容
# (?P<分组名>) 设置分组名
# (?P=分组名) 获取指定分组的内容
import reif __name__ == '__main__':# 需求1: 正则校验 html标签, 简单版.# 1. 定义html标签字符串.html_str1 = '<html>电子海鸥</html>'# 2. 正则校验.# 假设: 标签规则: 2到4位字母result = re.match('<[a-zA-Z]{2,4}>.*</[a-zA-Z]{2,4}>', html_str1)# 上述格式优化版, 加入: 分组思想.result = re.match(r'<([a-zA-Z]{2,4})>.*</\1>', html_str1)# 3. 打印匹配结果.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')print('-' * 21)# 需求2: 正则校验 html标签, 升级版.# 假设: 外部标签规则 2到4位字母, 内部标签规则: h + 1到6的数字# 1. 定义html标签字符串.html_str2 = '<html><h1>电子海鸥</h1></html>'# 2. 正则校验result = re.match(r'<[a-zA-Z]{2,4}><h[1-6]>.*</h[1-6]></[a-zA-Z]{2,4}>', html_str2)# 加入分组, 优化上述的代码.result = re.match(r'<([a-zA-Z]{2,4})><(h[1-6])>.*</\2></\1>', html_str2)# 扩展: 给分组设置组名.result = re.match(r'<(?P<A>[a-zA-Z]{2,4})><(?P<B>h[1-6])>.*</(?P=B)></(?P=A)>', html_str2)# 3. 打印匹配结果.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')