本文基于B站up主“麦叔编程”的正则表达式教程。
一、定义:
正则表达式:找到一串文本中符合某种模式(规律)的字符串。模式包括:
1)是什么字符;2)重复多少次;3)在什么位置(开头、结尾等);4)有哪些额外约束(如:固定数字位数,前后不能为数字)
二、熟悉正则表达式
下面为几个熟悉正则表达式的例子。依次从易到难,大概包括了正则表达式使用的几种情况。可以看完语法再看这个,会更容易懂。
level-1:固定的字符串。
import re
text = '数1,数2,数3,数1234567'
print(re.findall('123456', text)) # ['123456']
个人感觉:可以用来查找一个固定的字符串出现了多少次。
level-2:某一类字符
如:找出所有单个的数字
import re
text = '数1,数2,数3,数1234567'
print(re.findall(r'\d', text)) # ['1', '2', '3', '1', '2', '3', '4', '5', '6', '7']
相关知识点:
r:表示无特殊含义
正则:
\d:所有的数字 0-9
\D:
\s:
\w:
\W:
level-3:重复某一类字符
如:找出所有的数字:123这种
import re
text = '我买了1块钱的辣条,10块钱的苹果,500块钱的电饭锅,做了一顿-100的苹果炖辣条'
print(re.findall(r'\d+', text)) # ['1', '10', '500', '100']
在\d后面加上+,代表数字可以出现1到多次
level-4:组合level2
找出电话号码,座机号等符合一定规律的一串数字
import re
text = '我的电话不是17812345678,也不是17887654321,更不是12345678,也没有座机号:0571-66688899'
# 找到手机号
print(re.findall(r'\d{11}', text)) # ['17812345678', '17887654321']
# 找到座机号(4-8)
print(re.findall(r'\d{4}-\d{8}', text)) # ['0571-66688899']
# 找到座机号(4-8 或 3-7)
print(re.findall(r'\d{3,4}-\d{7,8}', text)) # ['0571-66688899', '021-8888777']
上述为指定数字的个数
level-5:多种情况
同时找出手机号和座机号
import re
text = '我的电话不是17812345678,也不是17887654321,更不是12345678,也没有座机号:0571-66688899和021-8888777'
# 找到手机号和座机号
print(re.findall(r'1\d{10}|\d{3,4}-\d{7,8}', text)) # ['17812345678', '17887654321', '0571-66688899', '021-8888777']
加上|符号,可以查找出前后不同的情况。是正则中的:管道。
level-6:限定位置
import re
text = '我的电话不是17812345678,也不是17887654321,更不是12345678,也没有座机号:0571-66688899和021-8888777'
msg = '17812345678不是我的手机号'
# 找到手机号和座机号
print(re.findall(r'^1\d{10}|^\d{3,4}-\d{7,8}', text)) # []
print(re.findall(r'^1\d{10}|^\d{3,4}-\d{7,8}', msg)) # ['17812345678']
加上^代表,所查找的内容要出现在文本的开头。
同时:$,代表在末尾。
level-7:内部约束
如:找到deidei,jiajia这种前后三个字母重复的字符串
import re
text = '路上一匹马,小明喊deidei,小红叫jiajia,小白叫它yuyu,马疯跑创飞了我,我只会aa'
#
print(re.findall(r'(\w{3})(\1)', text)) # [('dei', 'dei'), ('jia', 'jia')]
此处涉及到了分组()
三、写正则表达式-步骤
1、确定要获取的字符串包含几个部分
2、各个部分的字符分别是啥
3、各个子模式如何重复
4、是否有位置限制
5、是否有其他限制条件
以下为例子:
四、语法
下面为正则表达式的符号分类。
1、字符类别
a,b,c,1,2,3,-....字符常量,类似level-1中的操作,写啥找啥
\d:一个数字
\D:一个非数字字符
\w:一个任意的字母(即a-z,A-Z)、数字(0-9)、下划线(_)字符
\W:除字母、数字、下划线以外的任意字符
\s:一个空格(全角?非全角)
\S:一个非空格
.:代表除换行\n以外的任意一个字符
下面从范围内获取数据,返回的结果也是单个字符
[abcd]:代表a,b,c,d中的任意一个字符
[a-z]:从a-z中的任意一个,大写字母、数字范围写法相同
[^a-d]:取反,除了写的这几个外的任意一个字符
[\b]:退格==BackSpace
2、重复次数-量词
加上量词后 可以进行多个相同类型字符的获取,
* 0或多个 + 1或多个 ? 0或1个 {2} 2个 {2,5} 2到5个 {2,} 至少两个 {,5} 最多5个 如获取电话号码:r'1\d{10} '-代表1开头后面再跟10个连续的数字
3、等等
后面的写起来有点费劲,保存图片了,用的时候再查。
小扩展:|:是管道,可以分开多个需要匹配的规则
():分组,可以把分组里的东西看成组成想要的字符串的一个个个小单位
五、python的re模块
re.search():查找符合模式的字符,只返回第一个,返回Match对象
re.match():和search一样,但要求必须从字符串开头匹配
re.findall():返回所有匹配的字符串列表
re.finditer():返回一个迭代器,其中包含所有的匹配,也就是Match对象
re.sub():替换匹配的字符串,返回替换完成的文本
re.subn():替换匹配的字符串,返回替换完成的文本和替换的次数
re.split():用匹配表达式的字符串做分隔符分割原字符串
re.compile():把正则表达式编译成一个对象,方便后面使用
六、实际开发使用
1、查找需要的字符
import re
text = '我的名字是:快乐无花果,我的年纪是:18岁'
# 获取名字和岁数
name = re.findall('名字是:(.*?),', text)[0]
print(name) # 快乐无花果
age = re.findall('年纪是:(.*?)岁', text)[0]
print(age) # 18
七、相关链接
UP主:麦叔编程
一些更详细的正则表达式相关链接,带例子