超详解干货建议收藏正则表达式 & re模块

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超详解干货建议收藏正则表达式 & re模块相关的知识,希望对你有一定的参考价值。

正则表达式 & re模块

1. 正则表达式简介

概念

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这 些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一 种过滤逻辑(可以用来做检索,截取或者替换操作)。

正则表达式用于搜索、替换和解析字符串。正则表达式遵循一定的语法规则,使用非常 灵活,功能强大。使用正则表达式编写一些逻辑验证非常方便,例如电子邮件地址格式的验证。

正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符)操作 的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规 则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑,正则表达式是一种文本模式,模式描述在搜索文本时要匹配一个或多个字符串。

作用

  1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)。
  2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。
  3. 还可以对目标字符串进行替换操作。

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模块的主要内容,如果未能解决你的问题,请参考以下文章

Python高级详解 正则表达式(re模块)

最棒 Spring Boot 干货总结(超详细,建议收藏)

最新Spring Boot干货总结(超详细,建议收藏)

Python全栈 正则表达式(re模块正则接口全方位详解)

#yyds干货盘点# Python 内置模块之 re 库,一文搞定正则表达式初阶用法,滚雪球学 Python 第 13 篇

超详细Python正则表达式操作指南(re使用),一