超详解干货建议收藏正则表达式 & re模块
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超详解干货建议收藏正则表达式 & re模块相关的知识,希望对你有一定的参考价值。
正则表达式 & re模块
1. 正则表达式简介
概念
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这 些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一 种过滤逻辑(可以用来做检索,截取或者替换操作)。
正则表达式用于搜索、替换和解析字符串。正则表达式遵循一定的语法规则,使用非常 灵活,功能强大。使用正则表达式编写一些逻辑验证非常方便,例如电子邮件地址格式的验证。
正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符)操作 的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规 则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑,正则表达式是一种文本模式,模式描述在搜索文本时要匹配一个或多个字符串。
作用
- 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)。
- 可以通过正则表达式,从字符串中获取我们想要的特定部分。
- 还可以对目标字符串进行替换操作。
2. 正则表达式的使用(re模块)
Python 语言通过标准库中的 re 模块支持正则表达式。re 模块提供了一些根据正则表达 式进行查找、替换、分隔字符串的函数,这些函数使用一个正则表达式作为第一个参数。
re 模块常用的函数如下表所示。
2.1 match()
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,
**match()**就返回 None。语法格式如下:
re.match(pattern, string, flags=0)
函数参数说明如下表所示:
匹配字符串是正则表达式中最常用的一类应用。也就是设定一个文本模式,然后判断另外一个字符串是否符合这个文本模式。
如果文本模式只是一个普通的字符串,那么待匹配的字符串和文本模式字符串在完全相等的情况下,match 方法会认为匹配成功。如果匹配成功,则 match
方法返回匹配的对象, 然后可以调用对象中的 group
方法获取匹配成功的字符串,如果文本模式就是一个普通的字符串,那么 group
方法返回的就是文本模式字符串本身。
2.1.1 match 方法的使用
import re
s='hello python'
pattern='hello'
v=re.match(pattern,s)
print(v)
print(v.group())
print(v.span())
执行结果如图所示:
从上面的代码可以看出,进行文本模式匹配时,只要待匹配的字符串开始部分可以匹配文本模式,就算匹配成功。
2.1.2 match 方法中 flag 可选标志的使用
import re
s = 'hello Python!'
m=re.match('hello python',s,re.I) #忽略大小写
if m is not None:
print('匹配成功结果是:',m.group())
else:
print('匹配失败')
执行结果如下图所示:
3. 常用匹配符
3.1 常用匹配符的使用
import re
print('---.的使用---')
s = 'a'
s = 'A'
s = '1'
s = '_'
s = '\\n'
pattern = '.'
o = re.match(pattern, s)
print(o)
print('---\\d的使用---')
s = '0'
s = 'A'
pattern = '\\d'
o = re.match(pattern, s)
print(o)
print('---\\D的使用---')
s = '0'
s = 'A'
pattern = '\\D'
o = re.match(pattern, s)
print(o)
print('---\\s的使用---')
s = ' '
s = '\\n'
s = '\\t'
s = '_'
pattern = '\\s'
o = re.match(pattern, s)
print(o)
print('---\\S的使用---')
s = ' '
s = '\\n'
s = '\\t'
s = '_'
pattern = '\\S'
o = re.match(pattern, s)
print(o)
print('---\\w的使用---') # \\W 相反
s = 'z'
s = '8'
s = '#'
s = '_'
pattern = '\\w'
o = re.match(pattern, s)
print(o)
print('---[]的使用---')
s = '2'
pattern = '[2468]'
o = re.match(pattern, s)
print(o)
其中,匹配符“[]”
可以指定一个范围,例如:“[ok]”
将匹配包含“o”或“k”
的字符。同时“[]”
可以与\\w、\\s、\\d
等标记等价。例如,[0-9a-zA-Z]
等价于\\w,[^0-9]
等价于\\D
。
3.2 表示数量(匹配多个字符)
3.3 匹配手机号码
import re
# pattern = '\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d'
pattern = '1[356789]\\d\\d\\d\\d\\d\\d\\d\\d\\d'
s = '13345678901'
o = re.match(pattern, s)
print(o)
# 电话号码 区号-座机号 010-3762266 0342-8776262
如果要匹配电话号码,需要形如“\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d”
这样的正则表达式。其中表现 了 11
次“\\d”
,表达方式烦琐。而且某些地区的电话号码是 8 位数字,区号也有可能是 3 位或 4 位数字,因此这个正则表达式就不能满足要求了。正则表达式作为一门小型的语言, 还提供了对表达式的一部分进行重复处理的功能。例如,“*”
可以对正则表达式的某个部分重复匹配多次。这配符号称为限定符。下表列出了正则表达式中常用的限定符。
3.4 正则表达式中常用的限定符
利用`{}可以控制符号重复的次数。
3.5 数量的使用
import re
print('---*---')
pattern = '\\d*' # \\d匹配数字 * 可以有可以没有
s = '123qwe'
s = '123456qwe'
o = re.match(pattern, s)
print(o)
print('---+---')
pattern = '\\d*' # *零次或多次 + 至少一次
s = '123'
s = 'qwe'
o = re.match(pattern, s)
print(o)
print('---?---')
pattern = '\\d?' # *零次或多次 + 至少一次 ? : 0次或1次
s = '123'
s = '1qwe'
s = '2342qwe'
o = re.match(pattern, s)
print(o)
print('---{m}---')
pattern = '\\d{3}' # m次
s = '123'
# s = 'qwe'
o = re.match(pattern, s)
print(o)
print('---{m, n}---')
pattern = '\\d{2,5}' # 重复m次到n次
s = '12335'
# s = 'qwe'
o = re.match(pattern, s)
print(o)
print('---{m,}---')
pattern = '\\d{2,5}' # 至少重复至少m次
s = '12335'
# s = 'qwe'
o = re.match(pattern, s)
print(o)
3.6 匹配出一个字符串首字母为大写字符,后边都是小写字符,这些小写字母可有可无
pattern='[A-Z][a-z]*'
s='Hello world'
s='HEllo world'
v=re.match(pattern,s)
print(v)
3.7 匹配出有效的变量名
pattern='[A-Za-z_][0-9A-Za-z_]*'
pattern='[A-Za-z_]\\w*' # s='a'
s='ab'
s='_ab'
s='2ab'
v=re.match(pattern,s)
print(v)
3.8 匹配出 1-99 直接的数字
pattern='[1-9]\\d?'
s='1'
s='55'
s='99'
s='199'
v=re.match(pattern,s)
print(v)
3.9 匹配出一个随机密码 8-20 位以内 (大写字母 小写字母 下划线 数字)
pattern='\\w{8,20}'
s='12345678'
s='123__456'
v=re.match(pattern,s)
print(v)
4. 原生字符串
在大多数编程语言相同,正则表达式里使用“\\”
作为转义字符,这就可以能造成反斜杠困扰。示例如下:
s='c:\\\\a\\\\b\\\\c'
print(s)
执行结果如下图所示:
假如你需要匹配文本中的字符“\\”,那么使用编程语言表示的正则表达式里将需要 4 个反斜杠“\\\\”:前面两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python 里的原生字符串很好地解决了这个问 题,使用 Python 的 r 前缀。例如匹配一个数字的“\\d”可以写成 r“\\d”。有了原生字符串, 再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
4.2 r 前缀的使用
# 转义字符的使用
print('d:\\\\a\\\\b\\\\c')
print('\\nabc')
print('\\t123')
import re
s = '\\\\t123'
pattern = '\\\\\\\\t\\d*'
o = re.match(pattern, s)
print(o)
s = '\\\\t123'
pattern = r'\\\\t\\d*'
o = re.match(pattern, s)
print(o)
5. 边界字符
5.1 匹配符$的使用
#匹配 qq 邮箱, 5-10 位
pattern = '[\\d]{5,10}@qq.com'
#必须限制结尾的
# pattern = '[1-9]\\d{4,9}@qq.com$'
#正确的地址
v = re.match(pattern,'12345@qq.com')
#未限制结尾的前提下使用不正确的地址
# v = re.match(pattern,'12345@qq.comabc')
print(v)
5.2 匹配符^的使用
#匹配 qq 邮箱, 5-10 位
pattern = '[\\d]{5,10}@qq.com'
#必须限制结尾的
# pattern = '[1-9]\\d{4,9}@qq.com$'
#正确的地址
v = re.match(pattern,'12345@qq.com')
#未限制结尾的前提下使用不正确的地址
# v = re.match(pattern,'12345@qq.comabc')
print(v)
5.3 \\b 匹配单词边界
pattern = r'.*\\bab'
#ab 左边界的情况
v = re.match(pattern,'123 abr')
print(v)
pattern = r'.*ab\\b'
#ab 为右边界的情况
v = re.match(pattern,'wab')
print(v)
5.4 \\B 匹配非单词边界
#ab 不为左边界
pattern = r'.*\\Bab'
v = re.match(pattern,'123 abr')
print(v)
#ab 不为右边界
pattern = r'.*ab\\B'
v = re.match(pattern,'wab')
print(v)
6. search 方法
search 在一个字符串中搜索满足文本模式的字符串。语法格式如下:
re.search(pattern, string, flags=0)
函数参数与 match 方法类似,如下表所示:
6.1 search 方法的使用
import re
pattern = 'hello'
s = 'hello python'
m = re.search(pattern, s)
print(m.group())
执行结果如下图所示:
6.2 match 与 search 的区别
re.match
只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
;而 re.search
匹配整个字符串,直到找到一个匹配。
6.2.1 match 方法与 search 方法的使用对比
import re
#进行文本模式匹配,匹配失败,match 方法返回 None
m=re.match('love','I love you')
if m is not None:
print(m.group())
print('match 运行结果:',m)
#进行文本模式搜索,
m=re.search('love','I love you')
if m is not None:
print(m.group())
print('search 的运行结果:',m)
执行结果如下图所示:
6.3 匹配多个字符串
search 方法搜索一个字符串,要想搜索多个字符串,如搜索 aa、bb 和 cc,最简单的方 法是在文本模式字符串中使用择一匹配符号(|)。择一匹配符号和逻辑或类似,只要满足任何一个,就算匹配成功。
6.3.1 择一匹配符号(|)的使用
import re
s='aa|bb|cc'
#match 进行匹配
m=re.match(s,'aa')
#aa 满足要求,匹配成功
print(m.group())
m=re.match(s,'bb')
#bb 满足要求,匹配成功
print(m.group())
#search 查找
m=re.search(s,'Where is cc')
print(m.group())
从上面的代码可以看出,待匹配的字符串只要是 aa、bb 和 cc 中的任何一个就会匹配成功。
6.3.2 匹配 0-100 之间所有的数字
pattern = '[1-9]?\\d$|100$'
v = re.match(pattern,'0')
print(v)
v = re.match(pattern,'10')
print(v)
v = re.match(pattern,'100')
print(v)
v = re.match(pattern,'99')
print(v)
v = re.match(pattern,'200')
print(v)
6.3.3 字符集([])和择一匹配符(|)完成相同的效果
如果待匹配的字符串中,某些字符可以有多个选择,就需要使用字符集([]
),也就是 一对中括号括起来的字符串。例如,[xyz]
表示 x、y、z
三个字符可以取其中任何一个,相当 于“x|y|z”
,所以对单个字符使用或关系时,字符集和择一匹配符的效果是一样的。示例如下:
import re m=re.match('[xyz]','x')
#匹配成功
print(m.group())
m=re.match('x|y|z','x')
#匹配成功
print(m.group())
执行结果如下图所示:
6.3.4 字符集([])和择一匹配符(|)的用法,及它们的差异
import re
#匹配以第 1 个字母是 a 或者 b,第 2 个字母是 c 或者 d,如 ac、bc、ad、bd
m=re.match('[ab][cd]','aceg')
print(m)
#匹配以 ab 开头,第 3 个字母是 c 或者 d,如 abc、abd
m=re.match('ab[cd]','abcd')
print(m)
#匹配 ab 或者 cd
m=re.match('ab|cd','cd')
print(m)
执行结果如下图所示:
7. 分组
如果一个模式字符串中有用一对圆括号括起来的部分,那么这部分就会作为一组,可以通过 group 方法的参数获取指定的组匹配的字符串。当然,如果模式字符串中没有任何用圆括号括起来的部分,那么就不会对待匹配的字符串进行分组。
7.1 匹配座机号码
pattern = r'(\\d+)-(\\d{5,8}$)'
v = re.match(pattern,'010-66668888')
print(v)
print(v.group())
print(v.group(1))
print(v.group(2))
print(v.groups())
print(v.groups()[0])
print(v.groups()[1])
在上执行结果如下图所示:
7.2 \\num 的使用
#匹配出网页标签内的数据
s = '<html><title>我是标题</title></html>'
#优化前
# pattern = r'<.+><.+>.+</.+></.+>'
#优化后 可以使用分组 \\2 表示引用第 2 个分组 \\1 表示引用第 1 个分组
pattern = r'<(.+)><(.+)>.+</\\2></\\1>'
v = re.match(pattern,s)
print(v)
7.3 ?P<要起的别名> (?P=起好的别名)
s = '<html><h1>我是一号字体</h1></html>'
# pattern = r'<(.+)><(.+)>.+</\\2></\\1>'
#如果分组比较多的话,数起来比较麻烦,可以使用起别名的方法?P<要起的名字> 以及使 用别名(?P=之前起的别名)
pattern = r'<(?P<key1>.+)><(?P<key2>.+)>.+</(?P=key2)></(?P=key1)>'
v = re.match(pattern,s)
print(v)
使用分组要了解如下几点:
- 只有圆括号括起来的部分才算一组,如果模式字符串中既有圆括号括起来的部分,也有没有被圆括号括起来的部分,那么只会将被圆括号括起来的部分算作一组,其它的部分忽略。
- 用 group 方法获取指定组的值时,组从 1 开始,也就是说,group(1)获取第 1 组的值,group(2)获取第 2 组的值,以此类推。
- groups 方法用于获取所有组的值,以元组形式返回。所以除了使用 group(1)获取第 1 组的值外,还可以使用 groups()[0]获取第 1 组的值。获取第 2 组以及其它组的值的方式类似。
7.4 正则中的内容如何单独提取?
单独获取到正则中的具体内容可以给分组起名字
s = """
<div class='⻄游记'><span id='10010'>中国联通
</span></div>
"""
obj = re.compile(r"<span id='(?P<id>\\d+)'>(?P<name>\\w+)</span>", re.S)
result = obj.search(s)
print(result.group()) # 结果: <spanid='10010'>中国联</span>
print(result.group("id")) # 结果: 10010 # 获取id组的内容
print(result.group("name")) # 结果: 中国联通 #获取name组的内容
这里可以看到我们可以通过使用分组. 来对正则匹配到的内容进⼀步的进行筛选.
8. re 模块中其他常用的函数
8.1 sub 和 subn 搜索与替换
sub 函数和 subn 函数用于实现搜索和替换功能。这两个函数的功能几乎完全相同,都是将某个字符串中所有匹配正则表达式的部分替换成其他字符串。用来替换的部分可能是一个字符串,也可以是一个函数,该函数返回一个用来替换的字符串。
sub 函数返回替换后的结果,subn 函数返回一个元组,元组的第 1 个元素是替换后的结果,第 2 个元素是替换的总数。
语法格式如下:
re.sub(pattern, repl, string, count=0, flags=0)
参数说明:
8.1.1 sub 和 subn 方法的使用
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python 注释
num = re.sub(r'#.*$', "", phone)
print("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'\\D', "", phone)
print("电话号码是 : ", num)
#subn 函数的使用
result=re.subn(r'\\D', "", phone)
print(result)
print('替换的结果:',result[0])
print('替换的次数:',result[1])
在上执行结果如下图所示:
8.2 compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:
re.compile(pattern[, flags])
参数说明:
8.2.1 compile 函数的使用
import re
s='first123 line'
regex=re.compile(r'\\w+') #匹配至少一个字母或数字
m=regex.match(s)
print以上是关于超详解干货建议收藏正则表达式 & re模块的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# Python 内置模块之 re 库,一文搞定正则表达式初阶用法,滚雪球学 Python 第 13 篇