Python 正则表达式 re模块 最全面超详细总结

        想必字符串大家肯定都知道吧?在 Python 里我们常常需要对字符串进行操作,而在字符串对象本身就有许多内置的方法,大多数只需要对字符串简单处理的情况下,这些方法就已经足够了,比如 split join strip lstrip rstrip replace 等等。然鹅,这些都只是对字符串处理的普通操作,真正强大的高级操作是 正则表达式 !又正好,Python有一个内置的正则表达式模块,它就是  re 模块

【个人建议:想要灵活掌握re模块,建议在稍稍了解正则表达式语法的基础上(不必完全记住,因为一开始不好理解),再学习 re 模块的函数及类。在看re模块的代码示例时遇到不懂的语法规则,可以再回头看看正则表达式的语法,这样方便理解和掌握】 


正则表达式

        正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述匹配一系列匹配某个句法规则的字符串,通常被用来检索替换那些符合某个模式(规则)的文本。

———— 百度百科

匹配模式(pattern)—— 元字符

【注:下面的 RE(Regular Expression) 表示某个具体的正则表达式】 

元字符描述
^

该元字符在方括号外表示匹配字符串的开头,用于改变匹配起始位置

方括号内表示对方括号内的内容“取非”,如 [^0-9] 表示匹配单个非数字字符

$该元字符放在正则表达式末尾位置表示匹配字符串的末尾,用于改变匹配起始位置
.匹配除换行符(\n)以外的任意单个字符,加上 S 修饰符(见修饰符部分)后可匹配任意单个字符
?该修饰符用于其它修饰符后面,表示匹配模式为非贪婪的
|

可以认为是二目运算符,代表或者的含义,如 a|b 匹配字符 a 或者字符 b

不用圆括号进行分组时会影响整个正则表达式,如 a|bcd 匹配单个字符 a 或者字符串 bcd

[ ]只匹配满足方括号内正则表达式的单个字符,如 [abc] 只匹配字符 a 或字符 b 或字符 c
( )将满足圆括号内的正则表达式的字符串划分为一个组(group),便于分组分类
RE*匹配任意个连续的 RE
RE+匹配1个或多个连续的 RE
RE?匹配 0 个或 1 个 RE,非贪婪方式(见示例说明部分)
RE{n}匹配 n 个连续的 RE
RE{n,m}匹配 n 个到 m 个连续的 RE,省略 m(即 RE{n,} )则表示匹配 n 个及 n 个以上(无具体上限)连续的 RE
(?flags:RE)flags 代表修饰符,可在圆括号中(该分组)使用 i、m、x 等可选标志(必须小写),而不影响其它部分
(?-flags:RE)flags 代表修饰符,可在圆括号中(该分组)取消使用 i、m、x 等可选标志(必须小写),而不影响其它部分
(?#note)note 表示注释的内容,整个(?#note)代表注释,不影响匹配,只起解释说明作用
(?:RE)按顺序命名组时,忽略该组(即,一般非捕获分组),匹配结果包含 RE
(?=RE)

正向肯定预查(look ahead positive assert),匹配需满足 RE 正则表达式条件

匹配结果不包含 RE,且预查不消耗字符,下次匹配仍从 RE 开始

(?!RE)

正向否定预查(look ahead negative assert),匹配需不满足 RE 正则表达式条件

匹配结果不包含 RE,且预查不消耗字符,下次匹配仍从 RE 开始

\w

匹配单个的单词字符

其中单词字符是指数字字符、字母字符(不区分大小写)及下划线字符

\W匹配单个的非单词字符
\s匹配单个空白字符,空白字符包括空格、换行符\n、横向制表符\t、\r、换页符\f 等
\S匹配单个非空白字符
\d匹配单个数字字符
\D匹配单个非数字字符
\b

匹配单词字符串的边界,指单词字符串贴着非单词字符的部分

如 on\b 可以匹配 Python 中的 on,但不能匹配 cone 中的 on

\B匹配非单词字符串边界
\Z放于正则表达式末尾,匹配字符串是否结束
\A放于正则表达式起始,匹配字符串是否开始
\n等匹配单个换行符,类似的还有 \t、\r、\f 等
\num引用前面已经划分好的组,num 为一个正整数,代表组号

[A-B] 

或 [A-BC-D] 等

匹配单个字符,字符在 ASCII 字符集中的对应码位于字符 A 到字符 B 之间(包括 A 与 B

如:[0-9] 匹配单个数字;[a-z] 匹配单个小写字母;[!-@] 匹配标点符号及数字;

[a-zA-Z] 匹配单个字母字符;[!-/:-@] 匹配标点符号;注:[a-Z] 会报错!

可选标志(flags)—— 修饰符

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志,可有可无,多个标志可以通过按位或的符号(“|”) 来指定(如:re.M|re.X )。修饰符本身只是一个大写字母而已,但我们在Python里平时引入re模块时习惯用 import re,所以下面的修饰符在用的时候记得在其前面加上 re. 哦!

修饰符描述
A(ASCII)根据 ASCII 字符集解析字符,这个标志影响 \w, \W, \b, \B 等
I(IGNORECASE)匹配时忽略大小写,不添加该修饰符时默认对大小写敏感
L(LOCALE)

做本地化识别(locale-aware)匹配【】

M(MULTILINE)

多行匹配,影响 ^ 和 $,此时它们也以换行符为基准

S(DOTALL)

使 . 匹配包括换行符在内的所有字符,不添加该修饰符时默认为不包括换行符

U(UNICODE)根据 Unicode 字符集解析字符,这个标志影响 \w, \W, \b, \B 等
X(VERBOSE)

忽略正则表达式里的空格和注释,该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

T(TEMPLATE)

禁用回溯(实验性的,不推荐使用)

DEBUG

编译后转储模式(实验性的,不推荐使用)

re模块

        Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。

———— 菜鸟教程

re模块的类

【error类】

error(msg: str, pattern: str | bytes | None = ..., pos: int | None = ...)

re 模块所有异常的公共基类,一般用不到

【Match类】

匹配类,相当于匹配结果

【方法 group】无参数时返回匹配的字符串,若有参数,返回名为参数的分组的字符串

【方法 groups】无参数,返回一个包含所有分组字符串的元组

【方法 groupdict】无参数,类似于方法 groups,但返回一个字典

【方法 start】用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0

【方法 end】用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0

【方法 span】返回匹配开始与结束位置索引的元组(start(group), end(group)),参数为 group,用法类似于上面

【方法 expand】有一个 template 参数,接收字符串类型,返回一个字符串【具体啥用我也不清楚】

【Pattern类】

匹配模式类,相当于匹配规则,Pattern 类拥有很多类似于后面要讲到的函数的方法,但与下面的函数相比,它们又有区别

方法 findall

findall(string: str, pos: int = ..., endpos: int = ...)

与 findall 函数相比,findall 方法没有 pattern 参数和 flags 参数(这俩参数由 compile 函数指定),pos 参数指定字符串的起始位置,默认为 0,endpos 参数指定字符串的结束位置,默认为字符串的长度,返回值一样,是个列表

方法 finditer

finditer(string: str, pos: int = ..., endpos: int = ...)

参数描述与上面的 findall 方法类似,返回值和 finditer 函数的一样

方法 fullmatch

fullmatch(string: str, pos: int = ..., endpos: int = ...)

参数描述与上面的 findall 方法类似,返回值和 fullmatch 函数的一样

方法 match

match(string: str, pos: int = ..., endpos: int = ...)

参数描述与上面的 findall 方法类似,返回值和 match 函数的一样

方法 search

search(string: str, pos: int = ..., endpos: int = ...)

参数描述与上面的 findall 方法类似,返回值和 search 函数的一样

方法 split

split(string: str, maxsplit: int = ...)

没有 pattern 参数和 flags 参数,其余参数与返回值和 split 函数的一样

方法 sub

sub(repl: str | (Match[str]), string: str, count: int = ...)

没有 pattern 参数和 flags 参数,其余参数与返回值和 sub 函数的一样

方法 subn

subn(repl: str | (Match[str]), string: str, count: int = ...)

没有 pattern 参数和 flags 参数,其余参数与返回值和 subn 函数的一样

【RegexFlag类】

正则表达式修饰符类,可选标志参数,包括 A(ASCII)、I(IGNORECASE)、L(LOCALE)、M(MULTILINE)、S(DOTALL)、U(UNICODE)、X(VERBOSE)、T(TEMPLAT)和 DEBUG 等

re模块的函数

【compile函数】

函数语法

compile(pattern: AnyStr@compile, flags: _FlagsType = ...)

【参数 pattern】一个正则表达式字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

编译正则表达式函数,将正则表达式字符串编译为 Pattern 对象(Pattern[AnyStr@compile]),方便使用该正则表达式

代码示例

import re

#正则表达式含义:匹配单个非数字的字符
pattern_1 = re.compile(r'[^\d]')

#正则表达式含义:匹配单个数字字符或者单个小写字母字符
pattern_2 = re.compile(r'[0-9a-z]')

print(pattern_1.match('abc123').group())
#输出:a

print(pattern_2.search('ABCdef123').group())
#输出:d

print(pattern_1)
#输出:re.compile('[^\\d]')

【escape函数】

函数语法

escape(pattern: AnyStr@escape)

【参数 pattern】一个正则表达式字符串

函数对字符串中的转义字符进行还原,返回还原后的字符串

代码示例

import re

'''
此处不可直接用print输出,print会将还原后的字符又转义过去
用__repr__方法转换为原本的字符串后输出
不了解字符串类__repr__方法的应先去了解一下
'''
print(re.escape('Python.png').__repr__())
#输出:'Python\\.png'

print(re.escape('Python\Good').__repr__())
#输出:'Python\\\\png'

print(r'Python\Good'.__repr__())#见后面【转义与还原】部分了解更多
#输出:'Python\\Good'

【findall函数】

函数语法

findall(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

在 string 中寻找所有满足正则表达式的匹配结果,并将它们以列表形式返回,若没有满足条件的匹配结果,则返回空列表

代码示例

import re

#正则表达式含义:匹配两个连续的数字字符
outlist = re.findall('\d{2}','a12b34c56def780')

print(outlist)
#输出:['12', '34', '56', '78']

【finditer函数】

函数语法

finditer(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

和 findall 函数(见上)类似,唯一的区别是 finditer 函数返回的不是列表,而是一个迭代器(Iterator[Match[str]]) 

代码示例

import re

#正则表达式含义:匹配两个连续的数字字符
outiter = re.finditer('\d{2}','a12b34c56def780')

for i in outiter:
    print(i.group())
'''
输出:
12
34
56
78
'''

【fullmatch函数】

函数语法

fullmatch(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

与 match 函数类似,但它是完全匹配,即string必须从头到尾都满足 pattern 的模式,若满足则返回匹配结果(Match[str] 对象),否则返回 None

代码示例

import re

#正则表达式含义:匹配六个连续的非数字字符
Match_Object_1 = re.fullmatch('\D{6}','Python')

#正则表达式含义:匹配六个连续的单词字符
Match_Object_2 = re.fullmatch('\w{6}','JavaScript')

print(Match_Object_1.group())
#输出:Python

print(Match_Object_2.group())#没有完全匹配
#输出:AttributeError: 'NoneType' object has no attribute 'group'

【match函数】

函数语法

match(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

函数直接对 string 的开头进行匹配,匹配成功就返回匹配结果(Match[str] 对象),否则返回 None

代码示例

import re

#正则表达式含义:匹配六个连续的非数字字符
Match_Object_1 = re.match('\D{6}','Python')

#正则表达式含义:匹配六个连续的单词字符
Match_Object_2 = re.match('\w{6}','JavaScript')

print(Match_Object_1.group())
#输出:Python

print(Match_Object_2.group())
#输出:JavaSc

【purge函数】

函数语法

purge()

没有参数

清除正则表达式缓存,re 模块函数会对已编译的正则表达式对象进行缓存,在不同的 Python 版本中,缓存中已编译过的正则表达式对象的数目可能不同,而且没有文档记录,而 purge 函数能够用于清除这些缓存

代码示例

import re

#清除缓存
re.purge()#具体啥效果我也不太清楚...

【search函数】

函数语法

search(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

函数会从起始字符搜索整个 string,返回第一个满足正则表达式的匹配结果(Match[str] 对象),否则返回 None

代码示例

import re

#正则表达式含义:匹配3个连续的小写字母字符
#修饰符:I(IGNORECASE)忽略大小写,对大小写一视同仁
Match_Object_1 = re.search('[a-z]{3}','123_Oh_My_God_456',re.I)

#正则表达式含义:匹配字符串模式:_零个或多个连续单词字符_
Match_Object_2 = re.search('_\w*_','I_love_Python!')

print(Match_Object_1.group())
#输出:God

print(Match_Object_2.group())
#输出:_love_

【split函数】

函数语法

split(pattern: str | Pattern[str], string: str, maxsplit: int = ..., flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 string】要匹配的字符串

【参数 maxsplit】最大分割次数,从左往右计数,默认为对象ellipsis,即完全分割

【参数 flags】可选标志,修饰符,默认不进行修饰

与字符串的 split 方法类似,返回分割后的字符串,但分割规则由正则表达式决定,不了解字符串对象 split 方法的应先去了解该方法

代码示例

import re

#正则表达式含义:匹配任意个连续的数字字符
#最大分割次数为3(切4刀,产生5份)
outlist_1 = re.split('\d*','a1b22c333d4444e',4)

#正则表达式含义:匹配一个或多个连续的数字字符
#最大分割次数为3(切3刀,产生4份)
outlist_2 = re.split('\d+','a1b22c333d4444e',3)

print(outlist_1)
#输出:['', 'a', '', 'b', 'c333d4444e']

print(outlist_2)
#输出:['a', 'b', 'c', 'd4444e']

【sub函数】

函数语法

sub(pattern: str | Pattern[str], repl: str | (Match[str]), string: str, count: int = ..., flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 repl】要替换为的字符串或者函数(函数必须接收一个Match类,并返回一个字符串)

【参数 string】要进行操作的字符串

【参数 count】替换次数,从左往右计数,默认为对象ellipsis,即完全替换,若设为0也将完全替换

【参数 flags】可选标志,修饰符,默认不进行修饰

函数将把 string 中满足正则表达式的部分替换为 repl(如果repl是字符串),或者按照某种字符串生成规则(repl 为函数),替换为相应的字符串,返回替换后的字符串

代码示例

import re

#替换为固定的字符串
print(re.sub('\w*','!','123Python'))
#输出:!!(仔细体会为什么是两个感叹号)

def repl(match:re.Match):
    #repl替换函数
    #接收一个Match类
    #返回一个字符串
    return str(int(match.group())**2)

#替换为某种字符串(由替换函数决定)
print(re.sub('\d',repl,'123'))
#输出:149

【subn函数】

函数语法

subn(pattern: str | Pattern[str], repl: str | (Match[str]), string: str, count: int = ..., flags: _FlagsType = ...)

【参数 pattern】正则表达式字符串或者Pattern类

【参数 repl】要替换为的字符串或者函数(函数必须接收一个Match类,并返回一个字符串)

【参数 string】要进行操作的字符串

【参数 count】替换次数,从左往右计数,默认为对象ellipsis,即完全替换,若设为0也将完全替换

【参数 flags】可选标志,修饰符,默认不进行修饰

与 sub 函数类似,但是返回一个元组(tuple[str, int]),为替换后的字符串以及原字符串的总替换次数

代码示例

import re

#替换为固定的字符串
print(re.subn('\w+','!','123Python'))
#输出:('!', 1)

def repl(match:re.Match):
    #repl替换函数
    #接收一个Match类
    #返回一个字符串
    return str(int(match.group())**2)

#替换为某种字符串(由替换函数决定)
#替换次数:2次
print(re.subn('\d',repl,'123',2))
#输出:('143', 2)

【template函数】

函数语法

template(pattern: AnyStr@template | Pattern[AnyStr@template], flags: _FlagsType = ...)

【参数 pattern】一个正则表达式字符串

【参数 flags】可选标志,修饰符,默认不进行修饰

和 compile 函数类似,编译正则表达式函数,将正则表达式字符串编译为 Pattern 对象(Pattern[AnyStr@template]),但其返回的 Pattern 对象多了一个修饰符 T(TEMPLATE)

代码示例

import re

print(re.template('\d'))
#输出:re.compile('\\d', re.TEMPLATE)

print(re.template('\d').match('123').group())
#输出:1

示例说明

匹配单个字符

匹配单个字符的比较简单,下面这些元字符是用于匹配单个字符的

元字符描述(详细说明见元字符部分)
.匹配单个任意字符(除换行符外)
[ ]匹配单个方括号内字符
\d匹配单个数字字符
\D匹配单个非数字字符
\w匹配单个单词字符
\W匹配单个非单词字符
\s匹配单个空白字符
\S匹配单个非空白字符
\n等匹配单个换行符等

[A-B] 

或 [A-BC-D] 等

匹配单个字符,字符在 ASCII 字符集中的对应码位于字符 A 到字符 B 之间(包括 A 与 B)
import re

#点号元字符
print(re.match('.','\n').group())#点号元字符默认不包含换行符
#输出:AttributeError: 'NoneType' object has no attribute 'group'
print(re.match('.','\n',re.S).group().__repr__())#S修饰符使换行符被包括
#输出:'\n'

#方括号元字符
print(re.match('[abc]','b').group())#匹配abc任意其一
#输出:b
print(re.match('[!-/:-@]','?').group())#匹配标点符号
#输出:?

#\d元字符
print(re.match('\d','666').group())#匹配数字字符
#输出:6
print(re.match('\D','nb').group())#匹配非数字字符
#输出:n

#\w元字符
print(re.match('\w','abc').group())#匹配单词字符
#输出:a
print(re.match('\W','???').group())#匹配非单词字符
#输出:?

#\s元字符
print(re.match('\s',' ').group())#匹配空白字符
#输出:(此处输出了一个空格)
print(re.match('\S','\n').group())#匹配非空白字符
#输出:AttributeError: 'NoneType' object has no attribute 'group'

#特殊符号元字符(换行符等)
print(re.match('\n','\n').group().__repr__())#匹配换行符
#输出:'\n'
print(re.match('\t','\t').group().__repr__())#匹配横向制表符
#输出:'\t'

匹配多个字符

元字符描述(详细说明见元字符部分)
?RE? 表示匹配零个或一个 RE
+RE+ 表示匹配一个或多个连续的 RE
*RE* 表示匹配任意个连续的 RE
{ }RE{n} 表示匹配 n 个连续的 RE;RE{n,} 表示匹配 n 个及 n 个以上连续的 RE;RE{n,m} 表示匹配 n~m 个连续的 RE
|匹配 | 前面的字符串或者后面的字符串
import re

#问号元字符
print(re.match('What?','what',re.I).group())#匹配wha或者what,对大小写不敏感
#输出:what

#加号元字符
print(re.match('2+3','22223').group())#匹配一个或多个2再加上3
#输出:22223

#星号元字符
print(re.match('[abc]*','cba').group())#匹配任意个a或b或c
#输出:cba

#花括号元字符
print(re.match('(nb){3,}','NBnbNBnb',re.I).group())#匹配3个及3个以上的字符串nb,对大小写不敏感
#输出:NBnbNBnb

#竖线元字符
print(re.match('我去!|牛啊!','牛啊!').group())#匹配“我去!”或者“牛啊!”
#输出:牛啊!

匹配多组字符

在正则表达式里面使用圆括号会产生分组,若分组没有给定确切的组名,那么就从左往右按顺序以数字来命名,如

(123)([456]*)(\s+)

上面的正则表达式中就出现了 3 组,分别为 123、[456]* 和 \s+ ,组号就分别为 1、2 和 3,这都是属于捕获分组

特别说明

【捕获分组】分组且匹配,其内容将会被保存,组名按顺序以数字命名或者自定义具体组名,后续用命名进行引用

【非捕获分组】分组且匹配,没有组名,其内容不会被保存,后续将无法引用该组(或者说不需要用到)

元字符描述分组类型
( )将圆括号里的内容划分为一个组捕获分组
(?P<name>)将在 <name> 之后,右圆括号之前的内容划分为一个组,name 为该分组的组名捕获分组
\num引用前面已经划分好的组,num 为一个正整数,代表组号——
(?P=name)对有确切组名的分组进行引用,引用名为 name——
(?:RE)按顺序命名组时,忽略该组(即,一般非捕获分组),匹配结果包含 RE非捕获分组
(?=RE)

正向肯定预查(look ahead positive assert),匹配需满足 RE 正则表达式条件

匹配结果不包含 RE,且预查不消耗字符,下次匹配仍从 RE 开始

非捕获分组
(?!RE)

正向否定预查(look ahead negative assert),匹配需不满足 RE 正则表达式条件

匹配结果不包含 RE,且预查不消耗字符,下次匹配仍从 RE 开始

非捕获分组
(?flags:RE)flags 代表修饰符,可在该分组使用 i、m、x 等可选标志(必须小写),而不影响其它部分非捕获分组
(?-flags:RE)flags 代表修饰符,可在该分组取消使用 i、m、x 等可选标志(必须小写),而不影响其它部分非捕获分组
import re

#圆括号一般捕获分组
Match_Onject_1 = re.match('(\d+)([a-z]*)\\2','123abcABC',re.I)#\\2表示引用第2个分组内容(即[a-z]*)
print(Match_Onject_1.group())#没有参数,表示输出全部匹配结果
#输出:123abcABC
print(Match_Onject_1.group(1))#输出组号为1的分组(第1个分组)
#输出:123
print(Match_Onject_1.group(2))#输出组号为2的分组(第2个分组)
#输出:abc

#自定义组名捕获分组
Match_Onject_2 = re.match('(?P<First>[abc]{2,3})(?P=First)!','abab!')#自定义分组名为First
print(Match_Onject_2.group())#没有参数,表示输出全部匹配结果
#输出:abab!
print(Match_Onject_2.group('First'))#输出组名为First的分组
#输出:ab

#一般非捕获分组
Match_Onject_3 = re.match('([123]{2})(?:\w)(nb)\\2','22znbnb')#\\2表示第2个分组,为nb(忽略了\w)
print(Match_Onject_3.group())#没有参数,表示输出全部匹配结果
#输出:22znbnb(匹配结果中含有z)
print(Match_Onject_3.group(2))#输出组号为2的分组(第2个分组)
#输出:nb

#正向肯定预查
print(re.match('[Pp]ython(?=3\\.\d{2})','Python3.10').group())#版本号必须是3.\d{2}的形式时才能匹配
#输出:Python(匹配结果中不含3.10)

#正向否定预查
print(re.match('[Pp]ython(?!3\\.[0-9]{2})','python2.7').group())#版本号不是3.\d{2}的形式时才能匹配
#输出:python(匹配结果中不含2.7)

#分组内不区分大小写
print(re.match('(?i:p)p','Pp').group())
#输出:Pp

#分组内点号元字符不匹配换行符
print(re.match('(?-s:.).','\n\n',re.S).group().__repr__())
#输出:AttributeError: 'NoneType' object has no attribute 'group'

匹配的起始与末尾

用于改变或检测匹配位置的元字符有下面四种

元字符描述
^

该元字符放在正则表达式起始位置表示匹配字符串的开头,用于改变匹配起始位置

可以理解为:^ 所在的位置必须是匹配起始处(空字符)

$

该元字符放在正则表达式末尾位置表示匹配字符串的末尾,用于改变匹配结束位置

可以理解为:$ 所在的位置必须是匹配结尾处(空字符)

\A类似于 ^,放于正则表达式起始,匹配字符串是否开始
\Z类似于 $,放于正则表达式末尾,匹配字符串是否结束
import re

#匹配Python源文件的文件名
#不会检测文件名开头是否符合一些要求
print(re.search('\w*\.py','#Hello_World.pyi').group())
#输出:Hello_World.py

#利用 $ 判断结尾是否符合要求
print(re.search('\w*\.py$','Hello_World.pyi').group())#字符串末尾多了个i,而不是空字符
#输出:AttributeError: 'NoneType' object has no attribute 'group'

#利用 ^ 判断起始是否符合要求
print(re.search('^\w*\.py','#Hello_World.py').group())#字符串开头多了个#,而不是空字符
#输出:AttributeError: 'NoneType' object has no attribute 'group'

#利用 \Z 判断结尾是否符合要求
print(re.search('\w*\.py\Z','Hello_World.pyi').group())#字符串末尾多了个i,而不是空字符
#输出:AttributeError: 'NoneType' object has no attribute 'group'

#利用 \A 判断起始是否符合要求
print(re.search('\A\w*\.py','#Hello_World.py').group())#字符串开头多了个#,而不是空字符
#输出:AttributeError: 'NoneType' object has no attribute 'group'

匹配的贪婪与非贪婪

Python语言默认是贪婪的,意思就是说,总是尝试匹配尽可能多的字符,反之,非贪婪就是尝试匹配尽可能少的字符

在元字符 *?+{} 后面加上一个 ? 来指定它们为非贪婪模式

import re

#正则表达式含义:匹配一个或多个数字字符,贪婪模式,尽可能多
Match_Object_1 = re.match('\d+','123')

#正则表达式含义:匹配一个或多个数字字符,非贪婪模式,尽可能少
Match_Object_2 = re.match('\d+?','123')

print(Match_Object_1.group())
#输出:123

print(Match_Object_2.group())
#输出:1

字符的转义与还原

在python里,字符的转义是由反斜杠 \ 实现的,如换行符 \n、横向制表符 \t 等等,但我们有时候并不想要它们转义的含义,而是想要它们原本的含义,即原生字符串,这个时候就有两种做法了

温馨提示:print 函数打印字符串的结果是转义后的结果,若想要原生字符串,请调用 __repr__ 方法后再用 print 输出

第一种操作

把转义用的反斜杠给还原,这样就不会产生转义字符了,也就实现了还原的目的,具体操作就是在反斜杠前再加上一个反斜杠

'\n' ————> '\\n'
'\t' ————> '\\t'

但这样不能高效地解决问题,如果转义字符很多就比较麻烦,或者比如你要匹配单个的反斜杠文本字符 \,那么你要先将其在正则表达式语法格式中还原为 \\,在再字符串语法中将其还原为 \\\\,极其的麻烦,于是就有了第二种操作

第二种操作

在字符串前面加上一个小写的 r 字母,其含义应该是 raw 的缩写,也可能是 repr 的缩写?(个人猜测),可以将操作的字符串中的转义字符还原为普通字符

'\n' ————> r'\n'
'\t' ————> r'\t'

经典案例

改变日期格式

将美国格式的日期(2/8/2022)改为中国格式(2022/8/2)

import re

print(re.sub('(\d+)/(\d+)/(\d+)','\\3/\\2/\\1','2/8/2022'))
#输出:2022/8/2

print(re.sub('(\d+)/(\d+)/(\d+)',r'\3/\2/\1','2/8/2022'))
#输出:2022/8/2

判断变量名是否正确

任意给一段字符串,判断其是否能作为一个变量名

import re

print(re.fullmatch('[^\d]+\w+','_name_').group())
#输出:_name_

print(re.fullmatch('[^\d]+\w+','What_Fuc*!!!').group())
#输出:AttributeError: 'NoneType' object has no attribute 'group'

print(re.fullmatch('[^\d]+\w+','123Yeah').group())
#输出:AttributeError: 'NoneType' object has no attribute 'group'

匹配邮箱地址

给定一个地址,匹配其是否为邮箱地址

import re

print(re.match('\w{4,20}@(126|163|qq)\\.com\Z','10086@163.com').group())
#输出:10086@163.com

print(re.match('\w{4,20}@(126|163|qq)\\.com$','110119120@qq.com').group())
#输出:110119120@qq.com

【都看到这里了,不如给我点个小小的赞吧!】

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小康2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值