正则表达式
正则表达式前戏
我们日常生活中有很多地方都能用到正则表达式
比如说我们登录的时候输的手机号 其实内部需要校验是否是11位纯数字, 是不是13,15,17,18,19开头的,如果使用python代码来写的话就很长
# 手机号必须为11位纯数字,并且常规手机号开头位(13, 14, 15, 17, 18, 19)
# 上面条件使用python代码书写
# 获取用户手机号
phone_num = input('请输入您的手机号>>>:').strip()
# 比较数字是不是11位
if len(phone_num) == 11:
# 再验证是不是十一位都是数字
if phone_num.isdigit():
# 再验证开头是不是手机号的开头
if phone_num.startswith('13') or phone_num.startswith('15') or phone_num.startswith('17') or phone_num.startswith('18')or phone_num.startswith('19'):
print('手机号正确')
else:
print('手机号开头格式错误')
else:
print('输入手机号不是纯数字')
else:
print('手机号格式错误')
如果使用正则表达式代码就很简单:
import re
phone_number = input('please input your phone number>>>:').strip()
if re.match('^(13|14|15|17|18|19)[0-9]{9}$',phone_number):
print('手机号正确')
else:
print('手机号错误')
"""
正则表达式是一门独立的语言,用来匹配、校验、筛查、所需要的数据,
任何编程语言都可以使用正则,在python中直接使用内置模块re
"""
正则表达式测试网站
在线测试网站:http://tool.chinaz.com/regex/
字符组
"""字符组默认匹配方式是一个一个匹配"""
[0123456789] 匹配0到9任意一个数字
[0-9] 匹配0到9任意一个数字(简写)
[a-z] 匹配26个小写英文字母
[A-Z] 匹配26个大写因为英文字母
[0-9a-zA-Z] 匹配任意一个数字或大小写字母
"""字符组内所有的数据默认都是 或 的关系"""
特殊符号
"""特殊符号默认匹配方式是一个一个匹配"""
. 匹配除换行符以外的任意字符
\w 匹配数字,字母、下划线
\W 匹配非数字,非字母,非下划线
\d 匹配数字
^ 匹配字符串的开头
$ 匹配字符串的结尾
a|b 匹配a或者b 管道符意思是 或
() 给正则表达式分组,不影响表达式的匹配功能
[] 字符组 内部填写的内容默认都是或的关系
[^] 取反操作, 匹配除了字符组里面其他的所有字符
"""上尖号在中括号里面和在外面的意思完全不同"""
量词
"""量词必须跟在表达式的后面 不能单独使用 目的是增加匹配的字符数"""
正则表达式 默认情况都是贪婪匹配。尽可能多的匹配
* 匹配零次或多次 默认是多次
+ 匹配一次或多次 默认是多次
? 匹配零次或一次 主要用于非贪婪匹配
{n} 重复N次
{n,} 重复N次到更多次 默认是多次
{n,m} 重复n次到m次 默认是m次
贪婪匹配与非贪婪匹配
#正则 #待匹配的数
<.*> <script>alert(123)</script>
结果是一条
# <script>alert(123)</script>
"贪婪匹配就是匹配到最后一个>结束"
<.*?> <script>alert(123)</script>
结果是两条
# <script> </script>
"非贪婪匹配就是匹配到第一个> 为结尾"
"""贪婪匹配一般都是依据左右的符号为条件结束"""
取消转义符
\n \n 匹配的是换行符
\\n \n 匹配的是文本\n
\\\\n \\n 匹配的是文本\\n
在python中在字符串前面加r直接取消转义
\ 在正则表达式中可以取消后面\的特殊意义,如果出现多个\ 就要 写多个\来取消特殊含义
正则表达式的实战建议
我们是在日常中 经常遇到 校验 身份证码, 校验邮箱,校验手机号的这些程序里的功能。
其实内部都是正则表达式编写的
我们只需要弄得大概的意思,可以根据对应的功能在网上查找对应的正则表达式
例如校验身份证:
^[1-9][0-9]{14}
开头是1到9任意数字,中间用14个任意0-9之间数字组成, 15位的身份证号码
^[1-9][0-9]{16}[0-9x]
开头是1到9任意数字,中间用16个任意0-9之间数字组成 结尾是0-9之间任意数字或者是x 18位
re模块
re模块是做什么用的
python中无法直接使用正则, 需要借助re模块来使用
1.内置re模块
2.第三方的其他模块
常见操作方法
findall
import re
res = re.findall('j','jintianzhengsgijj') # re.findall(查找的字符, 待查找的文本)
print(res)
"""结果是一个列表,查找所有符合正则表达式的数据"""
finditer
import re
res = re.finditer('j','jintianzhengsgijj') # re.finditer(查找的字符, 待查找的文本)
print(res)
"""结果是一个迭代器对象,查找所有符合正则表达式的数据"""
print([obj.group() for obj in res]) # 获取方法
search
res = re.search('j','jintianzhengsgijj') #re.search(查找的字符, 待查找的文本)
print(res.group()) # j
"""匹配到一个符合条件的数据就立刻结束"""
match
res = re.match('j','jintianzhengsgijj') #re.match(查找的字符, 待查找的文本)
print(res.group())
"""匹配字符串的开头,如果不是接直接结束"""
compile
""" 提前先写好我们需要经常使用到的正则表达式,方便后面使用时不需要再重新写一遍"""
import re
obj = re.compile('\d+') # 匹配所有数字 \d数字 + 匹配多次 默认是贪婪匹配
res = obj.findall('23423422342342344')
print(res) # ['23423422342342344']
obj = re.compile('\d+')
res = obj.findall('2342asda422fdgd42344')
print(res) # ['2342', '422', '42344']
re.split('[分割条件1 2]','待分割数据' )
"""可以根据条件1先进行分割 后再根据条件2 对条件1分割后的结果再次分割"""
res = re.split('[1, 2]','怎么1回事2别瞎搞1' )
print(res) # ['怎么', '回事', '别瞎搞', '']
res = re.sub('\d', '2', '今天5点去做核酸5点没人', 1)
print(res) # 将字符串内数字 更换成 数字2, 1代表只更换一次 也可以更换成英文字母
res = re.subn('\d', '2', '今天5点去做核酸5点没人')
print(res) # 将字符串内的数字 更换成数字2 并返还更换了几次
补充
分组优先
findall默认是分组优先展示,如果正则表达式里有()那么就会优先展示该内容
res = re.findall('(a)bc','abcabc')
print(res) # ['a', 'a']
# 优先展示正则表达式括号内的 匹配内容
res = re.findall('(?:a)bc','abcabc')
print(res) # ['abc', 'abc']
# (?:) 括号前面加问号冒号 可以取消优先展示
res = re.search('(abc|bac)', 'abcbac')
print(res.group()) # abc
# 只会展示一个条件匹配到的内容
res = re.match('(abc|bac)', 'abcbac')
print(res.group()) # abc
# 只会展示一个条件匹配到的内容
分组别名
使用(?P<名字>查找的字符)进行分组别名,可以使用多个
res = re.search('(?P<name>abc)(?P<name1>bac)','abcbac')
print(res.group()) # abcbac
"""可以按照名字取值"""
print(res.group('name')) # abc
print(res.group('name1')) # bac
"""也可以按照索引位取值"""
print(res.group(0)) # 按照索引位 abcbac
print(res.group(1)) # 索引位1 abc
print(res.group(2)) # 索引位2 bac