一、正则基础
1、为什么使用正则
-
客户需求
例如:当需求需要判断一个字符串是否是手机号
-
解决方式
编写一个函数,给函数传入一个字符串,判断是手机号则返回True,否则返回False
-
代码
伪代码: def IsPhone(): # 判断长度为11 # 全部都是数字字符 # 以1开头 if.... True else: False
如果使用正则,会让这个问题变得非常简单。
2、正则与re模块简介
正则表达式:又称规则表达式。
(1)正则表达式(regular expression)描述了一种字符串匹配的模式(pattern)。
(2)正则匹配是一个 模糊的匹配(不是精确匹配)。
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、匹配锚字符
锚字符:判定是否按照规定开始或者结尾。
匹配 | 说明 |
---|---|
^ | 行首匹配,和[] 里的^ 不是一个意思 |
$ | 行尾匹配,和^ 一起使用 |
\A | 匹配字符串的开始,和^ 的区别是\A 只匹配整个字符串的开头,即使在re.M 模式下也不会匹配其他行的行首 |
\Z | 匹配字符串的结尾,和$ 的区别是\Z 只匹配整个字符串的结尾,即使在re.M 模式下也不会匹配其他行的行尾 |
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 |
# [] # 原子表
[a] # 匹配a
[ab] # 匹配a或者b
[abc] # 匹配a或者b后者c
[123] # 匹配1或者2或者3
[0-9] # 匹配任意一位数字
[a-z] # 匹配任意以为小写字母
[A-Z] # 匹配任意一位大写字母
[a-zA-Z] # 匹配任意大小写字母
[abc][0-9] # 匹配a或者b后者c和任意一位数字
1[3-9][0-9]{9} # {9} 代表前面的[0-9]9位 第一个数据为1,第二个数字从3-9,后9位数字随机
# ^ 限制开头 $ 限制结尾 一般用于组合
^1[3-9][0-9]{9}$ # 完全匹配 匹配的字符串中 必须完全符合才算匹配成功
# {} 代表前面正则匹配的n词
[a-z]{2} # 匹配俩位小写字母
[a-z][a-z] # 等同于上方
# {m,n} m-n之间的
[a-z]{2,5} # 匹配2-5个小写字母
# {m,} # 至少m个
[a-z]{2,} # 至少匹配2个小写字母
# ? 可有可无
-?[1-9] # 匹配正负1-9
# . 匹配换行符以外的任意字符
[.]
# * 代表前面的0次到多次 {0,}
# .* 组合 了解 贪婪模式 匹配换行符以外的任意字符任意次
# .*? 组合 非贪婪模式 匹配换行符以外的任意字符任意次
# + 匹配一次到多次 {1,}
# .+? 非贪婪模式 匹配换行符以外的任意字符至少1次
# | 代表或
[a-z]|[0-9] # 匹配字母或数字
# () # 1.作为一个单元 2.作为子存储
三、re模块中常用函数
通用flags(修正符)
值 | 说明 |
---|---|
re.I | 是匹配对大小写不敏感 |
re.M | 多行匹配,影响到^ 和$ |
re.S | 使.匹配包括换行符在内的所有字符 |
通用函数
1、match()函数 (用于匹配-完全匹配)
- 原型
def match(pattern, string, flags=0)
- 参数
参数 | 说明 |
---|---|
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
- 功能
匹配成功返回 匹配的对象 。
匹配失败 返回 None。
-
注意:从第一位开始匹配 只匹配一次
-
代码
import re # 导入re正则模块
# match 只匹配一次 必须从第一位开始
print(re.match("a", '123456')) # None
print(re.match("[a-z]", '123456')) # None
print(re.match("[a-z]", '123x456')) # None
print(re.match("[a-z][a-z]", '123x456')) # None
print(re.match("1[3-9][0-9]{9}", 'x15611833906a')) # None
print(re.match("1[3-9][0-9]{9}$", '15611833906').group()) # 完全匹配
2、searce()函数 (模糊搜索-模糊匹配)
-
原型
def search(pattern, string, flags=0)
-
参数
参数 说明 pattern 匹配的正则表达式(一种字符串的模式) string 要匹配的字符串 flags 标识位,用于控制正则表达式的匹配方式 -
功能
扫描整个字符串string,并返回第一个pattern模式成功的匹配。
匹配失败 返回 None。
-
注意:
只要字符串包含就可以。只匹配一次。
-
代码
import re # search 只匹配一次 print(re.search("a", '123456')) # None print(re.search("[a-z]", '123456')) # None print(re.search("[a-z]", '123x456')) print(re.search("[a-z][a-z]", '123x456')) # None print(re.search("[a-z][a-z]", '123ab456')) print(re.search("[a-z][a-z]", '123ax456b')) print(re.search("1[3-9][0-9]{9}", '15611833906')) print(re.search("1[3-9][0-9]{9}", '15611833906a')) print(re.search("1[3-9][0-9]{9}", 'x15611833906a')) print(re.search("^1[3-9][0-9]{9}", 'x15611833906a')) # None print(re.search("^1[3-9][0-9]{9}", '15611833906a')) print(re.search("^1[3-9][0-9]{9}$", '15611833906a')) # 完全匹配 # None print(re.search("^1[3-9][0-9]{9}$", '15611833906')) # 完全匹配 print(re.search("^1[3-9][0-9]{9}$", '1561183390')) # 完全匹配 # None print(re.search("^1[3-9][0-9]{9}$", '15611833906').group()) # 完全匹配
-
注意
match()与search()的区别
相同点:
都只匹配一次。
不同点:
- search是在要匹配的字符串中 包含正则表达式的内容就可以。
- match 必须第一位就开始匹配 否则匹配失败。
3、findall()函数(返回列表)
-
原型
def findall(pattern, string, flags=0)
-
参数
参数 说明 pattern 匹配的正则表达式(一种字符串的模式) string 要匹配的字符串 flags 标识位,用于控制正则表达式的匹配方式 -
功能
扫描整个字符串string,并返回所有匹配的pattern模式结果的字符串列表。
-
示例
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)给正则里面匹配的 加上圆括号 会将括号里面的内容进行 单独的返回 #[('<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>'] res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr) #(2) 不区分大小写的匹配 #['<a href="http://www.baidu.com">百度</a>', '<A href="http://www.taobao.com">淘宝</A>'] res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr,re.I) #['<a href="http://www.baidu.com">百度</a>'] res = re.findall("<[aA] href=\"http://www\..*?\.com\">.*?</[aA]>",myStr) # (3) 使.支持换行匹配 #['<a href="http://www.baidu.com">百度</a>', '<a href="http://www.id97.com">电\n影网站</a>'] res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr,re.S) # # (4) 支持换行 支持不区分大小写匹配 # ['<a href="http://www.baidu.com">百度</a>', '<A href="http://www.taobao.com">淘宝</A>', '<a href="http://www.id97.com">电\n影网站</a>'] res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr,re.S|re.I) #
-
贪婪与非贪婪模式
<H1>Chapter 1 - 介绍正则表达式</H1>
**贪婪:**下面的表达式匹配从开始小于符号 (<) 到关闭 H1 标记的大于符号 (>) 之间的所有内容。
/<.*>/
**非贪婪:**如果您只需要匹配开始和结束 H1 标签,下面的非贪婪表达式只匹配
/<.*?>/
如果只想匹配开始的 H1 标签,表达式则是:
/<\w+?>
4、finditer()函数
- 原型
def finditer(pattern, string, flags=0)
- 参数
参数 | 说明 |
---|---|
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
flags | 标识位,用于控制正则表达式的匹配方式 |
-
功能
与findall()类似,返回一个迭代器。
-
代码
import re res = re.finditer('\w', '12hsakda1') print(res) for i in res: print(i) # 循环遍历出每一个值
5、split()函数
-
作用:切割字符串
-
原型:
def split(patter, string, maxsplit=0, flags=0)
- 参数
参数 | 说明 |
---|---|
pattern | 匹配的正则表达式(一种字符串的模式) |
string | 要匹配的字符串 |
maxsplit | 最大拆分次数 默认拆分全部 |
flags | 标识位,用于控制正则表达式的匹配方式 |
-
示例
import re myStr = "asdas\rd&a\ts12d\n*a3sd@a_1sd" #通过特殊字符 对其进行拆分 成列表 # ['asdas', 'd', 'a', 's', '', 'd', '', 'a', 'sd', 'a', '', 'sd'] res = re.split("[^a-z]",myStr) # ['asdas', 'd', 'a', 's12d', '', 'a3sd', 'a_1sd'] res = re.split("\W",myStr)
6、修正符
-
作用
对正则进行修正
-
使用
search()/match()/findall()/sub()/subn()/finditer() 等函数 flags参数的使用。
-
修正符
re.I 不区分大小写匹配。
re.M 多行匹配 影响到^ 和 $ 的功能。
re.S 使.可以匹配换行符 匹配任意字符。
-
使用
re.I
print(re.findall('[a-z]','AaBb')) # ['a', 'b'] print(re.findall('[a-z]','AaBb', flags=re.I)) # ['A', 'a', 'B', 'b']
re.M
myStr = """asadasdd1\nbsadasdd2\ncsadasdd3""" print(re.findall('^[a-z]', myStr, )) # ['a'] print(re.findall('\A[a-z]', myStr)) # ['a'] print(re.findall('\d$', myStr)) # ['3'] print(re.findall('\d\Z', myStr)) # ['3'] # re.M print(re.findall('^[a-z]', myStr, flags=re.M)) # ['a', 'b', 'c'] print(re.findall('\A[a-z]', myStr, flags=re.M)) # ['a'] print(re.findall('\d$', myStr, flags=re.M)) # ['1', '2', '3'] print(re.findall('\d\Z', myStr, flags=re.M)) # ['3']
re.S
print(re.findall('<b>.*?</b>','<b>b标签</b>')) print(re.findall('<b>.*?</b>','<b>b标\n签</b>', flags=re.S))
四、正则高级
1、分组&起名称
-
概念
处理简单的判断是否匹配之外,正则表达式还有提取子串的功能,用()表示的就是要提取的分组
-
代码
import re myStr = "abcd1" print(re.search("(?P<number>\d+)", myStr).group(0)) # 当有多个子存储的时候 使用别名比较方便 # print(re.search("(?P<number>\d+)", myStr).group('number')) print(re.search("(?P<asd>\d+)", myStr).group('asd'))
-
说明
- 正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来
- group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串
2、编译 、compile()函数
-
概念
当在python中使用正则表达式时,re模块会做两件事,一件是编译正则表达式,如果表达式的字符串本身不合法,会报错。另一件是用编译好的正则表达式提取匹配字符串
-
编译优点
如果一个正则表达式要使用几千遍,每一次都会编译,出于效率的考虑进行正则表达式的编译,就不需要每次都编译了,节省了编译的时间,从而提升效率
-
compile()函数
-
原型
def compile(pattern, flags=0)
-
作用
将pattern模式编译成正则对象。
-
参数
参数 说明 pattern 匹配的正则表达式(一种字符串的模式) flags 标识位,用于控制正则表达式的匹配方式 -
flags
值 说明 re.I 是匹配对大小写不敏感 re.M 多行匹配,影响到^和$ re.S 使.匹配包括换行符在内的所有字符 -
返回值
编译好的正则对象
-
示例
import re re_phone = re.compile(r"(0\d{2,3}-\d{7,8})") print(re_phone, type(re_phone))
-
-
编译后其他方法的使用
原型
def match(self, string, pos=0, endpos=-1) def search(self, string, pos=0, endpos=-1) def findall(self, string, pos=0, endpos=-1) def finditer(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>')