一、正则基础
1、为什么使用正则
- 需求
判断一个字符串是否是手机号 - 解决
编写一个函数,给函数一个字符串,如果是手机号则返回True,否则返回False - 代码
defisPhone(phone): # 长度为11# 全部都是数字字符# 以1开头passifisPhone("13812345678"): print("是手机号") else: print("不是手机号")
- 注意
如果使用正则会让这个问题变得简单
2、正则与re模块简介
概述:正则表达式,又称规则表达式
正则表达式(regular expression)描述了一种字符串匹配的模式(pattern)
正则匹配是一个 模糊的匹配(不是精确匹配)
re:python自1.5版本开始增加了re模块,该模块提供了perl风格的正则表达式模式,re模块是python语言拥有了所有正则表达式的功能
- 如下四个方法经常使用
- match()
- search()
- findall()
- finditer()
二、正则表达式
1、匹配单个字符与数字
匹配 | 说明 |
. | 匹配除换行符以外的任意字符,当flags被设置为re.S时,可以匹配包含换行符以内的所有字符 |
[] | 里面是字符集合,匹配[]里任意一个字符 |
[0123456789] | 匹配任意一个数字字符 |
[0-9] | 匹配任意一个数字字符 |
[a-z] | 匹配任意一个小写英文字母字符 |
[A-Z] | 匹配任意一个大写英文字母字符 |
[A-Za-z] | 匹配任意一个英文字母字符 |
[A-Za-z0-9] | 匹配任意一个数字或英文字母字符 |
[^lucky] | []里的^称为脱字符,表示非,匹配不在[]内的任意一个字符 |
^[lucky] | 以[]中内的某一个字符作为开头 |
\d | 匹配任意一个数字字符,相当于[0-9] |
\D | 匹配任意一个非数字字符,相当于[^0-9] |
\w | 匹配字母、下划线、数字中的任意一个字符,相当于[0-9A-Za-z_] |
\W | 匹配非字母、下划线、数字中的任意一个字符,相当于[^0-9A-Za-z_] |
\s | 匹配空白符(空格、换页、换行、回车、制表),相当于[ \f\n\r\t] |
\S | 匹配非空白符(空格、换页、换行、回车、制表),相当于[^ \f\n\r\t] |
2、匹配锚字符
锚字符:用来判定是否按照规定开始或者结尾
匹配 | 说明 |
^ | 行首匹配,和[]里的^不是一个意思 |
$ | 行尾匹配 |
3、限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。
匹配 | 说明 |
(xyz) | 匹配括号内的xyz,作为一个整体去匹配 一个单元 子存储 |
x? | 匹配0个或者1个x,非贪婪匹配 |
x* | 匹配0个或任意多个x |
x+ | 匹配至少一个x |
x{n} | 确定匹配n个x,n是非负数 |
x{n,} | 至少匹配n个x |
x{n,m} | 匹配至少n个最多m个x |
x|y | |表示或的意思,匹配x或y |
三、re模块中常用函数
通用flags(修正符)
值 | 说明 |
re.I | 是匹配对大小写不敏感 |
re.S | 使.匹配包括换行符在内的所有字符 |
通用函数
- 获取匹配结果
- 使用group()方法 获取到匹配的值
- groups() 返回一个包含所有小组字符串的元组(也就是自存储的值),从 1 到 所含的小组号。
1、match()函数
- 原型
defmatch(pattern, string, flags=0)
- 功能
匹配成功返回 匹配的对象
匹配失败 返回 None - 获取匹配结果
- 使用group()方法 获取到匹配的值
- groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
- 注意:从第一位开始匹配 只匹配一次
- 参数
参数 | 说明 |
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
- 代码
importreres=re.match('\d{2}','123') print(res.group()) #给当前匹配到的结果起别名s='3G4HFD567're.match("(?P<value>\d+)",s) print(x.group(0)) print(x.group('value'))
2、searce()函数
- 原型
def search(pattern, string, flags=0)
- 功能
扫描整个字符串string,并返回第一个pattern模式成功的匹配
匹配失败 返回 None - 参数
参数 | 说明 |
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
- 注意:
只要字符串包含就可以
只匹配一次 - 示例
importreres=re.search('[a-z]', '131A3ab889s') print(res) print(res.group()
- 注意与search的区别相同点:都只匹配一次不同点:
- search是在要匹配的字符串中 包含正则表达式的内容就可以
- match 必须第一位就开始匹配 否则匹配失败
3、findall()函数(返回列表)
- 原型
deffindall(pattern, string, flags=0)
- 功能
扫描整个字符串string,并返回所有匹配的pattern模式结果的字符串列表 - 参数
参数 | 说明 |
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
- 示例
myStr="""<a href="http://www.baidu.com">百度</a><A href="http://www.taobao.com">淘宝</A><a href="http://www.id97.com">电影网站</a><i>我是倾斜1</i><i>我是倾斜2</i><em>我是倾斜2</em>"""# html里是不区分大小写# (1)给正则里面匹配的 加上圆括号 会将括号里面的内容进行 单独的返回res=re.findall("(<a href=\"http://www\.(.*?)\.com\">(.*?)</a>)",myStr) #[('<a href="http://www.baidu.com">百度</a>', 'baidu', '百度')]# 括号的区别res=re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr) #['<a href="http://www.baidu.com">百度</a>']#(2) 不区分大小写的匹配res=re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr,re.I) #['<a href="http://www.baidu.com">百度</a>', '<A href="http://www.taobao.com">淘宝</A>']res=re.findall("<[aA] href=\"http://www\..*?\.com\">.*?</[aA]>",myStr) #['<a href="http://www.baidu.com">百度</a>']# (3) 使.支持换行匹配res=re.findall("<a href="http://www..?.com">.?</a>",myStr,re.S) ## (4) 支持换行 支持不区分大小写匹配res=re.findall("<a href="http://www..?.com">.?</a>",myStr,re.S|re.I) #print(res)
4、finditer()函数
- 原型
deffinditer(pattern, string, flags=0)
- 功能
与findall()类似,返回一个迭代器 - 参数
参数 | 说明 |
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
- 代码
importreres=re.finditer('\w', '12hsakda1') print(res) print(next(res)) foriinres: print(i)
5、split()函数
- 作用:切割字符串
- 原型:
defsplit(patter, string, maxsplit=0, flags=0)
- 参数
pattern 正则表达式
string 要拆分的字符串
maxsplit 最大拆分次数 默认拆分全部
flags 修正符 - 示例
importremyStr="asdas\rd&a\ts12d\n*a3sd@a_1sd"#通过特殊字符 对其进行拆分 成列表res=re.split("[^a-z]",myStr) res=re.split("\W",myStr)
6、修正符
- 作用
对正则进行修正 - 使用
search/match/findall/finditer 等函数 flags参数的使用 - 修正符
re.I 不区分大小写匹配
re.S 使.可以匹配换行符 匹配任意字符 - 使用
re.I
print(re.findall('[a-z]','AaBb')) print(re.findall('[a-z]','AaBb', flags=re.I))
- re.S
print(re.findall('<b>.*?</b>','<b>b标签</b>')) print(re.findall('<b>.*?</b>','<b>b标\n签</b>', flags=re.S))
四、正则高级
1、分组&起名称
- 概念
处理简单的判断是否匹配之外,正则表达式还有提取子串的功能,用()表示的就是要提取的分组 - 代码
#给当前匹配到的结果起别名s='3G4HFD567're.match("(?P<value>\d+)",s) print(x.group(0)) print(x.group('value'))
- 说明
- 正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来
- group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串
2、编译
- 概念
当在python中使用正则表达式时,re模块会做两件事,一件是编译正则表达式,如果表达式的字符串本身不合法,会报错。另一件是用编译好的正则表达式提取匹配字符串 - 编译优点
如果一个正则表达式要使用几千遍,每一次都会编译,出于效率的考虑进行正则表达式的编译,就不需要每次都编译了,节省了编译的时间,从而提升效率 - compile()函数
- 原型
defcompile(pattern, flags=0)
- 作用
将pattern模式编译成正则对象 - 参数
参数 | 说明 |
pattern | 匹配的正则表达式(一种字符串的模式) |
flags | 标识位,用于控制正则表达式的匹配方式 |
- flags
值 | 说明 |
re.I | 是匹配对大小写不敏感 |
re.S | 使.匹配包括换行符在内的所有字符 |
- 返回值
编译好的正则对象 - 示例
importrere_phone=re.compile(r"(0\d{2,3}-\d{7,8})") print(re_phone, type(re_phone))
- 编译后其他方法的使用
原型
defmatch(self, string, pos=0, endpos=-1) defsearch(self, string, pos=0, endpos=-1) deffindall(self, string, pos=0, endpos=-1) deffinditer(self, string, pos=0, endpos=-1)
- 参数
参数 | 说明 |
string | 待匹配的字符串 |
pos | 从string字符串pos下标开始 |
endpos | 结束下标 |
- 示例
s1="lucky's phone is 010-88888888"s2="kaige's phone is 010-99999999"ret1=re_phone.search(s1) print(ret1, ret1.group(1)) ret2=re_phone.search(s2) print(ret2, ret2.group(1))
3、贪婪与非贪婪
- 贪婪模式 贪婪概念:匹配尽可能多的字符
- .+ 匹配换行符以外的字符至少一次
- .* 匹配换行符以外的字符任意次
- 实例
res=re.search('<b>.+</b>', '<b></b><b>b标签</b>') res=re.search('<b>.*</b>', '<b>b标签</b><b>b标签</b><b>b标签</b><b>b标签</b>')
- 非贪婪模式
非贪婪概念:尽可能少的匹配称为非贪婪匹配,*?、+?即可 - .+? 匹配换行符以外的字符至少一次 拒绝贪婪
- .*? 匹配换行符以外的字符任意次 拒绝贪婪
- 实例
res=re.search('<b>.+?</b>', '<b>b标签</b><b>b标签</b>') res=re.search('<b>.*?</b>', '<b>b标签</b><b>b标签</b><b>b标签</b><b>b标签</b>')