文章目录
1. 了解正则表达式
1.1 什么是正则表达式
- 正则表达式是一种可以让复杂的字符串问题变得简单的工具。
- 正则并不是Python特有的语法(不属于Python),所有的高级编程语言都支持正则,正则的语法是通用的。
- 不管通过正则表达式解决的是什么问题,写正则的时候都是在使用正则表达式描述字符串的规则。
1.2 re模块
- re模块是Python用来支持正则表达式的一个模块,模块中包含了所有和正则相关的函数。
fullmatch(正则表达式, 字符串)
- 判断正则表达式和指定的字符串是否完全匹配(判断整个字符串是否符合正则表达式所描述的规则)
匹配成功返回匹配对象,匹配失败返回None。
2. 正则语法
2.1 匹配类符号
-
普通符号 - 在正则表达式中表示符号本身的符号
from re import fullmatch result = fullmatch(r'abc', 'abc') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='abc'> '''
-
. - 匹配任意一个字符
from re import fullmatch result = fullmatch(r'..abc', 'd2abc') print(result) # 运行结果 ''' <re.Match object; span=(0, 5), match='d2abc'> '''
-
\d - 匹配任意一个数字字符
from re import fullmatch result = fullmatch(r'a\dc', 'a5c') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='a5c'> '''
-
\s - 匹配任意一个空白字符
空白字符 - 能产生空白效果的字符,例如:空格、换行、水平制表符from re import fullmatch result = fullmatch(r'a\sc', 'a\tc') print(result) result = fullmatch(r'\d\d\s.ab', '34 吗ab') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='a\tc'> <re.Match object; span=(0, 6), match='34 吗ab'> '''
-
\D - 匹配任意一个非数字字符
from re import fullmatch result = fullmatch(r'a\Dc', 'a*c') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='a*c'> '''
-
\S - 匹配任意一个非空白字符
from re import fullmatch result = fullmatch(r'a\Sc', 'a c') print(result) result = fullmatch(r'a\Sc', 'a1c') print(result) # 运行结果 ''' None <re.Match object; span=(0, 3), match='a1c'> '''
-
[字符集] - 匹配字符集中任意一个字符
正则表达式 | 描述 |
---|---|
[abc] | 匹配a或者b或者c |
[abc\d] | 匹配a或者b或者c或者任意数字 |
[1-9] | 匹配1到9中的任意一个数字 |
[a-z] | 匹配任意一个小写字母 |
[A-Z] | 匹配任意一个大写字母 |
[a-zA-Z\d_] | 匹配字母数字或者下划线 |
[\u4e00-\u9fa5] | 匹配任意一个中文字符 |
注意:[]中减号放在两个字符之间表示谁到谁(确定的方式是根据字符编码值大小确定的); 如果减号不在两个字符之间,就表示一个普通的减号
from re import fullmatch
result = fullmatch(r'a[MN12]b', 'aNb')
print(result)
result = fullmatch(r'a[MN\d]b', 'a4b')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 3), match='aNb'>
<re.Match object; span=(0, 3), match='a4b'>
'''
-
[^字符集]
- 匹配不在字符集中的任意一个字符from re import fullmatch result = fullmatch(r'a[^MN]b', 'a是b') print(result) result = fullmatch(r'a[^\u4e00-\u9fa5]b', 'a-b') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='a是b'> <re.Match object; span=(0, 3), match='a-b'> '''
2.2 匹配次数
-
* - 0次或多次(任意次数)
注意:*在谁的后面控制的就是谁的次数from re import fullmatch result = fullmatch(r'\d*abc', '123411232abc') print(result) # 运行结果 ''' <re.Match object; span=(0, 12), match='123411232abc'> '''
-
+ - 1次或者多次(至少一次)
from re import fullmatch result = fullmatch(r'a+123', 'aaaaa123') print(result) # 运行结果 ''' <re.Match object; span=(0, 8), match='aaaaa123'> '''
-
? - 0次或1次
from re import fullmatch result = fullmatch(r'A?123', 'A123') print(result) # 运行结果 ''' <re.Match object; span=(0, 4), match='A123'> '''
-
{}
{} | 描述 |
---|---|
{M,N} | M到N次 |
{M,} | 至少M次 |
{,N} | 最多N次 |
{N} | N次 |
from re import fullmatch
result = fullmatch(r'[a-z]{3,5}123', 'bambk123')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 8), match='bambk123'>
'''
2.3 贪婪和非贪婪
- 当匹配次数不确定的时候(*、+、?、{M,N}、{M,}、{,N}、{N}),匹配模式分为贪婪和非贪婪两种,默认是贪婪。
- 在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果, 非贪婪取最少次数对应的匹配结果
(匹配次数不确定的地方,有多种匹配方式都可以匹配成功,贪婪取最多次数, 非贪婪取最少次数)
- 贪婪模式:*、+、?、{M,N}、{M,}、{,N}
- 非贪婪模式:*?、+?、??、{M,N}?、{M,}?、{,N}?
from re import match
# 贪婪模式
result = match(r'a.+b', 'amb计算bxxbmn')
print(result)
# 非贪婪模式
result = match(r'a.+?b', 'amb计算bxxbmn')
print(result)
# 注意:如果匹配结果只有一种可能,那么贪婪和非贪婪的结果一样
result = match(r'a.+b', 'ambxx')
print(result)
result = match(r'a.+?b', 'ambxx')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 9), match='amb计算bxxb'>
<re.Match object; span=(0, 3), match='amb'>
<re.Match object; span=(0, 3), match='amb'>
<re.Match object; span=(0, 3), match='amb'>
'''
3. 分组和分支
3.1 分组
findall(正则表达式, 字符串)
- 获取字符串中所有满足正则表达式的子串
-
整体 - 将正则表达式中的一部分作为一个整体进行相关操作
from re import fullmatch result = fullmatch(r'(\d\d[A-Z]{2})+', '23HK89MB') print(result) # 运行结果 ''' <re.Match object; span=(0, 8), match='23HK89MB'> '''
-
重复 - 可以在正则表达式中通过
\M
来重复它前面的第M个分组的匹配结果。from re import fullmatch result = fullmatch(r'(\d{2})([a-z]{3})=\2\1{3}', '23mkl=mkl232323') print(result) # 运行结果 ''' <re.Match object; span=(0, 15), match='23mkl=mkl232323'> '''
-
捕获 - 只获取正则表达式中的分组匹配到的结果(分为手动和自动捕获两种)
from re import findall message = '我今年18岁,月薪50000元,身高180,体重70公斤,8块腹肌。每年交300元的腾讯会员费。房贷每月3000元,车贷每月2200元。' result = findall(r'(\d+)元', message) print(result) # 运行结果 ''' ['50000', '300', '3000', '2200'] '''
3.2 分支
正则1|正则2|正则3|...
- 匹配可以和多个正则中任意一个正则匹配的字符串
from re import fullmatch
# a234b、amjkb
result = fullmatch(r'a\d{3}b|a[a-z]{3}b', 'a232b')
print(result)
# 注意:如果想要正则表达式中的一部分实现多选一的效果,变化的部分用分组表示
result = fullmatch(r'a(\d{3}|[a-z]{3})b', 'amklb')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 5), match='a232b'>
<re.Match object; span=(0, 5), match='amklb'>
'''
4. 转义符号
4.1 转义符号
正则中的转义符号,就是在本身具备特殊功能或者特殊意义的符号前加’',让这个符号变成一个普通符号。
from re import fullmatch
result = fullmatch(r'\+\d+', '+23')
print(result)
result = fullmatch(r'\([a-z]+\)', '(msnd)')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 3), match='+23'>
<re.Match object; span=(0, 6), match='(msnd)'>
'''
4.2 []里面的转义符号
单独存在有特殊意义的符号(+、*、?、.等),在[]中特殊意义会自动消失
from re import fullmatch
result = fullmatch(r'a[M\-N]b', 'a-b')
print(result)
# 运行结果
'''
<re.Match object; span=(0, 3), match='a-b'>
'''
5. 检测类符号
注意:检测类符号是在匹配成功的情况下,检测检测类符号所在的位置是否符号相关要求
-
\b - 检测是否是单词边界
单词边界:可以将两个单词区分开的符号都是单词边界,比如:空白符号、英文标点符号、字符串开头和字符串结尾from re import findall message = '203mn45,89 司机34kn;23;99mll==910,230 90=' result = findall(r'\d+\b', message) print(result) result = findall(r'\b\d+', message) print(result) result = findall(r'\b\d+\b', message) print(result) # 运行结果 ''' ['45', '89', '23', '910', '230', '90'] ['203', '89', '23', '99', '910', '230', '90'] ['89', '23', '910', '230', '90'] '''
-
\B - 检测是否不是单词边界
from re import findall message = '203mn45,89 司机34kn;23;99mll==910,230 90=' result = findall(r'\B\d+\B', message) print(result) # 运行结果 ''' ['03', '4', '34', '9', '1', '3'] '''
-
^ - 检测是否是字符串开头
from re import findall message = '203mn45,89 司机34kn;23;99mll==910,230 90=' result = findall(r'^\d+', message) print(result) # 运行结果 ''' ['203'] '''
-
$ - 检测是否是字符串结尾
from re import findall message = '203mn45,89 司机34kn;23;99mll==910,230 90=' result = findall(r'.{5}$', message) print(result) # 运行结果 ''' ['0 90='] '''
6. re模块常用函数
先导入所有模块from re import *
6.1 常用函数
-
fullmatch(正则表达式, 字符串)
- 完全匹配,判断整个字符串是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空result = fullmatch(r'\d{3}', '234') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='234'> '''
-
match(正则表达式, 字符串)
- 匹配字符串开头,判断字符串开头是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空result = match(r'\d{3}', '823介绍数据库') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='823'> '''
-
search(正则表达式, 字符串)
- 获取字符串中第一个能够和正则匹配的子串,能找到返回匹配对象,找不到返回空result = search(r'\d{3}', 'ba203还是678说') print(result) # 运行结果 ''' <re.Match object; span=(2, 5), match='203'> '''
-
findall(正则表达式, 字符串)
- 获取字符串中所有满足正则的子串,返回一个列表,列表中的元素是字符串。
注意:如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配到的结果)result = findall(r'\d{3}', 'ba203还是678说kk0222jksn就是23311') print(result) # 运行结果 ''' ['203', '678', '022', '233'] '''
-
finditer(正则表达式, 字符串)
- 获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是每个子串对应的匹配对象result = finditer(r'\d{3}', 'ba203还是678说kk0222jksn就是23311') print(result) print(list(result)) # 运行结果 ''' <callable_iterator object at 0x0000027FEEC3A790> [<re.Match object; span=(2, 5), match='203'>, <re.Match object; span=(7, 10), match='678'>, <re.Match object; span=(13, 16), match='022'>, <re.Match object; span=(23, 26), match='233'>] '''
-
split(正则表达式, 字符串)
- 将字符串中所有满足正则的子串作为切割点对字符串进行切割str1 = '123aMKnb嗑生嗑死aKKssa923b===' # 将str1中的a和b作为切割点对字符串进行切割 result = split(r'a|b', str1) print(result) # 运行结果 ''' ['123', 'MKn', '嗑生嗑死', 'KKss', '923', '==='] '''
-
sub(正则表达式, 字符串1, 字符串2)
- 将字符串2中所有满足正则的子串都替换成字符串1result = sub(r'\d+', '+', 'ba203还是678说kk0222jksn就是23311') print(result) # 运行结果 ''' ba+还是+说kk+jksn就是+ '''
6.2 匹配对象
result = search(r'(\d{3})([A-Z]{2})', '-=2设计师234KM222哈哈宿舍239KH')
print(result)
# 运行结果
'''
<re.Match object; span=(6, 11), match='234KM'>
'''
-
直接获取整个正则表达式对应的匹配结果:
匹配对象.group()
print(result.group()) # 运行结果 ''' 234KM '''
-
手动捕获某个分组对应的匹配结果:
匹配对象.group(分组数)
print(result.group(1)) print(result.group(2)) # 运行结果 ''' 234 KM '''
-
获取匹配结果在原字符串中的位置:
匹配对象.span()
print(result.span()) print(result.span(2)) # 运行结果 ''' (6, 11) (9, 11) '''
6.3 参数
-
匹配忽略大小写:
(?i)
from re import * result = fullmatch(r'(?i)abc', 'AbC') print(result) # 运行结果 ''' <re.Match object; span=(0, 3), match='AbC'> '''
-
单行匹配:
(?s)
(了解!)
-
多行匹配(默认):匹配的时候.不能和换行(\n)进行匹配
-
单行匹配:匹配的时候.可以和换行(\n)进行匹配
from re import * result = fullmatch(r'abc.123', 'abc\n123') print(result) result = fullmatch(r'(?s)abc.123', 'abc\n123') print(result) # 运行结果 ''' None <re.Match object; span=(0, 7), match='abc\n123'> '''