正则表达式(python版最全面,最易懂)

news/2025/2/13 3:45:34/

正则表达式

正则表达式英文称regular expression

定义:正则表达式是一种文本模式匹配的工具,用于字符串的搜索,匹配和替换。在excel,word以及其他的文本编辑器都可直接适配。

一、基本匹配规则

  • 字面值字符:例如字母、数字、空格等,可以直接匹配它们自身。

  • 特殊字符:例如点号 .、星号 *、加号 +、问号 ? 等,它们具有特殊的含义和功能。

  • 字符类:用方括号 [ ] 包围的字符集合,用于匹配方括号内的任意一个字符。

  • 元字符:例如 \d\w\s 等,用于匹配特定类型的字符,如数字、字母、空白字符等。

  • 量词:例如 {n}{n,}{n,m} 等,用于指定匹配的次数或范围。

  • 边界符号:例如 ^$\b\B 等,用于匹配字符串的开头、结尾或单词边界位置。

1.字符匹配

普通字符匹配:直接匹配文本中的字符,如abc表示直接匹配文本中包含为“abc”的字符

元字符匹配:元字符具有特殊的含义,例如 \d 匹配任意数字字符,\w 匹配任意字母数字字符,. 匹配任意字符(除了换行符)等。

常见的元字符如下:

元字符含义示例
.匹配任意单个字符(换行符除外)a.c 匹配 "abc"、"a1c"
^匹配字符串开头^abc 匹配 "abc123"
$匹配字符串结尾abc$ 匹配 "123abc"
*匹配前一个字符 0 次或多次a* 匹配 "", "a", "aaa"
+匹配前一个字符 1 次或多次a+ 匹配 "a", "aaa"
?匹配前一个字符 0 次或 1 次a? 匹配 "", "a"
{n}匹配前一个字符 n 次a{3} 匹配 "aaa"
{n,m}匹配前一个字符 n 到 m 次a{2,4} 匹配 "aa", "aaa", "aaaa"
[]匹配字符集合中的任意一个字符[abc] 匹配 "a", "b", "c" [a-z] 匹配小写字母 a 到 z 的任意一个 [0-9] 匹配数字 0 到 9 的任意一个 [^...]匹配不在括号内的任意字符(字符集的否定)
|或运算 
\转义字符,转义元字符或定义特殊字符\d\s\w, C:\\Users\\Qiu
\d匹配任何数字,相当于 [0-9] 
\D匹配任何非数字字符,相当于 [^0-9] 
\w匹配任何单词字符(字母、数字、下划线),相当于 [a-zA-Z0-9_] 
\W匹配任何非单词字符,相当于 [^a-zA-Z0-9_] 
\s匹配任何空白字符(空格、制表符、换行符等) 
\S匹配任何非空白字符 
()用于分组和捕获子表达式。(\d{4})-(\d{2}-\d{2})\d{4}\d{2}-\d{2}分为两组,可以对这两组进行捕获以及后期直接引用 (\w{3})(\1) 表示匹配连续两段的字母,如abbabb
(?: )用于分组但不捕获子表达式。 

2.量词匹配

  • *:匹配前面的模式零次或多次。

  • +:匹配前面的模式一次或多次。

  • ?:匹配前面的模式零次或一次。

  • {n}:匹配前面的模式恰好 n 次。

  • {n,}:匹配前面的模式至少 n 次。

  • {n,m}:匹配前面的模式至少 n 次且不超过 m 次。

3.字符类

  • [ ]:匹配括号内的任意一个字符。例如,[abc] 匹配字符 "a"、"b" 或 "c"。

  • [^ ]:匹配除了括号内的字符以外的任意一个字符。例如,[^abc] 匹配除了字符 "a"、"b" 或 "c" 以外的任意字符。

4.边界匹配(定位符)

定位符用来描述字符串或单词的边界,^$ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。

  • ^:匹配字符串的开头。

  • $:匹配字符串的结尾。

  • \b:匹配单词边界。

  • \B:匹配非单词边界。

5.分组和捕获

  • ( ):用于分组和捕获子表达式。

  • (?: ):用于分组但不捕获子表达式。

6.特殊字符

  • \:转义字符,用于匹配特殊字符本身。

  • .:匹配任意字符(除了换行符)。

  • |:用于指定多个模式的选择。

7.分组与引用

() 表示分组,匹配子表达式并捕获;() 会把每个分组里的匹配的值保存起来, 多个匹配值可以通过数字 n 来查看(n 是一个数字,表示第 n 个捕获组的内容)。如:(\w{3})(\1) 表示匹配连续两段的字母,如abbabb

  • (\d{4})-(\d{2}-\d{2})\d{4}\d{2}-\d{2}分为两组,可以对这两组进行捕获以及后期直接引用

但用圆括号会有一个副作用,使相关的匹配会被缓存,此时可用 ?: 放在第一个选项前来消除这种副作用。即?: 仅于分组但不捕获子表达式。

其中?:为非捕获元之一,非捕获元表示不会将表达式内容包含在结果当中。同等的非捕获元还有?=?!

8.正、负向零宽断言

?=正向零宽断言 (Positive Lookahead)

  • exp1(?=exp2) 查找在exp2前面的exp1,且exp2不会包含在结果当中

  • (?<=exp2)exp1 表示查找在exp2前面的exp1,且exp2不会包含在结果当中

python">import re​pattern = r"I love (?=python)" # 匹配 "python" 前面带有 "I love " 的部分text = "I love python, I love coding."​match = re.search(pattern, text)if match:print(match.group())  # 输出:I love

 ​

?!:负向零宽断言 (Negative Lookahead)

  • exp1(?!exp2) 查找在 exp2 后面不跟exp1,且 exp2 不会包含在结果当中。

  • (?<!exp2)exp1 查找在 exp2 前面不跟exp1,且 exp2 不会包含在结果当中。

python"> import re​pattern = r"I love (?!python)"text = "I love coding, I love python." # 匹配不以 "python" 结尾的 "I love "​matches = re.findall(pattern, text)print(matches)  # 输出:['I love ']
 

?=?!的区别:

特性?=(正向断言)?!(负向断言)
断言结果后面 必须是 pattern后面 不能是 pattern
是否消耗字符
适用场景验证后续内容符合预期排除后续内容不符合预期

9.贪婪与非贪婪匹配

*+ 限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配。

贪婪匹配:尽可能多地匹配。

  • 示例:a.*b 匹配 "a123b456b" 中的 "a123b456b"。

非贪婪匹配:尽可能少地匹配。

  • 语法:在元字符后加 ?

  • 示例:a.*?b 匹配 "a123b456b" 中的 "a123b"。

案例:如<.*>会匹配到如下html标签内的所有值

 

01bc494e04d5dcb9aae8e5bccc2dca1f.png

但是如果我们只需要匹配一个<h1>标签,我们可以使用非贪婪匹配:<.*?>

 

9549c921b8f09080f553b6f3a607f540.png

通过在 *+? 限定符之后放置 ?,该表达式从"贪婪"表达式转换为"非贪婪"表达式或者最小匹配。

10.标记/修饰符(flag)

符号作用示例
iignore - 不区分大小写将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。
gglobal - 全局匹配查找所有的匹配项。
mmulti line - 多行匹配使边界字符 ^$ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
s特殊字符圆点 . 中包含换行符 \n默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。
  • i表示不区分大小写:

 

c7b4b02ff0a45e7ca96546fd584d960d.png

  • m表示多行匹配(每行都进行匹配)

 

211cf631de45563f687beecd40408cc8.png

  • 默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 之后, . 中包含换行符 \n

 

9ebfe0e5e71e78b7634693259852a504.png

python re库内的正则表达式支持的修饰符(可选标志)

 

4dd11d72e3d832f07d3472e5adaadbad.png

re.IGNORECASE (re.I):忽略大小写。

re.MULTILINE (re.M):多行模式,^$ 会匹配每一行的开头和结尾。

re.DOTALL (re.S):单行模式,使 . 匹配换行符。

re.VERBOSE (re.X):允许在正则表达式中添加注释和多行书写。

其他标志如 re.ASCIIre.LOCALE 等。

二、Python正则表达式API使用

Python 提供了 re 模块用于操作正则表达式。

 

99e675674bac602e7e344f2770f21b79.png

函数含义
re.match从字符串开头匹配,返回 Match 对象
re.search在字符串中搜索第一个匹配
re.findall返回所有匹配结果的列表
re.finditer返回所有匹配结果的迭代器
re.sub替换匹配到的内容
re.split按正则表达式分割字符串

1.查找

方法作用描述
re.match从字符串的开头尝试匹配正则表达式,只返回第一个匹配的对象。
re.search搜索整个字符串,返回第一个匹配的对象。
re.findall搜索所有符合正则表达式的内容,返回匹配结果的列表。
re.finditer搜索所有符合正则表达式的内容,返回一个迭代器(每项是 Match 对象)。

1.re.match/re.search

re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到一个匹配。

 re.match(pattern, string, flags=0) # pattern正则表达式;string需要匹配的字符;flag修饰符模式。match匹配字符串的开始,如果字符串开始不符合正则表达式,则返回None,否则返回一个Match对象re.search(pattern, string, flags=0) # re.search 匹配整个字符串,匹配成功返回一个Match对象,否则返回None

Match对象方法:

  • group(num=0) 当查找字符串分组时,group(num) 将返回对应num组的元组(1开始分组),group(0)/group(num)表示全部匹配字符串。

  • groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

 
python">import re​line = "Cats are smarter than dogs"​# 匹配字符串的开始,如果开始不成功,则匹配失败matchObj = re.match(r"dogs", line, re.M | re.I)  # return:Noneif matchObj:print(matchObj.group())else:print("No match!!") # No match!!​# 匹配整个字符串直到找到至少一个匹配matchObj = re.search(r"dogs", line, re.M | re.I)  # return:dogsif matchObj:print(matchObj.group()) # dogselse:print("No match!!")分组text2 = "18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166,0571-52152177"m1 = re.search(r"(\d{4})-(\d{8})", text2)  # 返回一个Match对象,调用Match对象的group方法获取返回值print(m1.group())  # 0571-52152166print(m1.group(1))  # 0571,取表达式的第一组匹配值(\d{4})print(m1.group(2))  # 52152166,取表达式的第二组匹配值(\d{8})

2.findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

 re.findall(pattern, string, flags=0)或pattern.findall(string[, pos[, endpos]])
  • pattern 匹配模式。

  • string 待匹配的字符串。

  • pos 可选参数,指定字符串的起始位置,默认为 0。

  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

python">import reresult1 = re.findall(r'\d+','runoob 123 google 456')pattern = re.compile(r'\d+')   # 查找数字result2 = pattern.findall('runoob 123 google 456')result3 = pattern.findall('run88oob123google456', 0, 10)print(result1) # ['123', '456']print(result2) # ['123', '456']print(result3) # ['88', '12']​多个匹配模式,返回元组列表import re​result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')print(result) # [('width', '20'), ('height', '10')]

3.re.finditer

findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

python">re.finditer(pattern, string, flags=0)import reit = re.finditer(r"\d+","12a32bc43jf3") for match in it: print(match.group())12 32 43 3

findallfinditer的区别

  • findall返回的可能是元组列表,也可能是字符串列表,取决于正则表达式内是否分组

  • finditer返回的是Match对象的迭代器

2.替换

替换功能可以用正则表达式匹配到的部分内容进行替换,主要通过 re.subre.subn 方法实现。

方法作用描述
re.sub替换匹配到的内容,返回替换后的新字符串。
re.subn替换匹配到的内容,返回元组 (新字符串, 替换次数)
  • sub:返回替换后的字符串。

  • subn:返回包含替换后字符串和替换次数的元组。

1.re.sub&re.subn

 re.sub(pattern, repl, string, count=0, flags=0) # 前三个为必选参数,后两个为可选参数。
  • pattern : 正则中的模式字符串。

  • repl : 替换的字符串,也可为一个函数。

  • string : 要被查找替换的原始字符串。

  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

  • flags : 编译时用的匹配模式,数字形式。

 
python">import rephone = "2004-959-559 # 这是一个电话号码"# 删除注释num = re.sub(r'#.*$', "", phone)print ("电话号码 : ", num)# 移除非数字的内容num = re.sub(r'\D', "", phone)print ("电话号码 : ", num)# 当repl 参数是一个函数import re# 将匹配的数字乘以 2def double(matched):value = int(matched.group('value'))return str(value * 2)s = 'A23G4HFD567'print(re.sub('(?P<value>\d+)', double, s)) # A46G8HFD1134

subn和sub用法一样,只是subn会额外将替换的次数一起封装成元组返回

python">text = "abc,adfasda,Abc,ABC"sub = re.sub(r"(abc)", "***", text, flags=re.I)subn = re.subn(r"(abc)", "***", text, flags=re.I)print(sub)  # re.sub返回替换后的字符串,***,adfasda,***,***print(subn)  # re.subn返回替换后的字符串和替换次数的元组,('***,adfasda,***,***', 3)

 

3.分割split

 re.split(pattern, string[, maxsplit=0, flags=0])
  • pattern 正则表达式

  • string 需要匹配的字符串

  • maxsplit 分割次数,maxsplit=1 分割一次,默认为 0表示不限制次数。

  • flags 标志位

python"> text6 = "abc,  ddd? xxx. fff! asd"split = re.split(r"\s*[,?!.]\s*", text6)  # 将【,?!.】符号以及旁边的空格作为分隔符分割字符串,返回一个字符串数组print(split)  # ['abc', 'ddd', 'xxx', 'fff', 'asd']​re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割# ['hello world']

 

4.compile

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:

 re.compile(pattern[, flags])
  • pattern : 一个字符串形式的正则表达式

  • flags 可选,表示匹配模式,比如忽略大小写,多行模式等

  • 返回 RegexObject 对象,该对象可以调用匹配方法(如 matchsearchfindall 等)。

python"> # 编译正则表达式pattern = re.compile(r"\d+")​# compile# 使用编译的正则对象进行匹配和查找result1 = pattern.findall("There are 3 cats and 4 dogs.")result2 = pattern.findall("There are 6 cats and 8 dogs.")print(result1)  # 输出 ['3', '4']print(result2)  # 输出 ['6', '8']

re.compile() 是处理复杂正则表达式的最佳选择,尤其是需要频繁使用相同的正则时。它能提高代码效率、增强可读性,是 Python 正则表达式模块中非常重要的功能。

 


http://www.ppmy.cn/news/1564630.html

相关文章

jenkins docker 遇到 /var/run/docker.sock: permission denied 解决方案

使用 Jenkins Docker 会碰到 /var/run/docker.sock:/var/run/docker.sock: permission denied 这个错误&#xff0c;最暴力的解决方式就是放大限 777。比较优雅的解决方式是将 jenkins 加到 docker 组中。 groupadd -g 999 docker usermod -aG docker jenkins那个 gid 一定要保…

vue+高德API搭建前段经济页面

一、模板部分&#xff08;<template>&#xff09; html <template><div class"content"><div><dv-border-box-8 :reverse"true"><div class"head"><div class"head_content"><h1>1…

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)边缘检测

OpenCV中边缘检测四种常用算子&#xff1a; &#xff08;1&#xff09;Sobel算子 Sobel算子是一种基于梯度的边缘检测算法。它通过对图像进行卷积操作来计算图像的梯度&#xff0c;并将梯度的大小作为边缘的强度。它使用两个3x3的卷积核&#xff0c;分别用于计…

redis做为缓存,mysql的数据如何与redis进行同步呢?

Redis作为缓存与MySQL之间的数据同步问题&#xff0c;特别是涉及到双写一致性&#xff08;即缓存与数据库的写操作要保持一致&#xff09;时&#xff0c;通常有两种常见的解决方案。它们分别适用于不同的一致性要求和延迟容忍度。以下是两种常见的解决方案的详细解释&#xff1…

与 Spring Boot 的无缝集成:ShardingSphere 快速集成实践

ShardingSphere 是一个轻量级的开源分布式数据库中间件&#xff0c;它支持分库分表、分布式事务、读写分离等功能。它能够与各种应用框架进行集成&#xff0c;其中与 Spring Boot 的集成非常流行&#xff0c;因为它能够帮助开发者在 Spring Boot 项目中快速实现高性能的分布式数…

【Azure 架构师学习笔记】- Azure Function (2) --实操1

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Function 】系列。 接上文【Azure 架构师学习笔记】- Azure Function (1) --环境搭建和背景介绍 前言 上一文介绍了环境搭建&#xff0c;接下来就在本地环境下使用一下。 环境准备 这里我下载了最新的VS studio&…

鸿蒙动态路由实现方案

背景 随着CSDN 鸿蒙APP 业务功能的增加&#xff0c;以及为了与iOS、Android 端统一页面跳转路由&#xff0c;以及动态下发路由链接&#xff0c;路由重定向等功能。鸿蒙动态路由方案的实现迫在眉睫。 实现方案 鸿蒙版本动态路由的实现原理&#xff0c;类似于 iOS与Android的实…

C++中.h文件中的实现方法

在 C 中&#xff0c;.h 文件和 Java 中的接口有一些相似之处&#xff0c;但它们的作用和用法还是有很大区别。具体来说&#xff0c;.h 文件通常用于声明&#xff0c;但也可以包含一些实现&#xff0c;特别是在某些特殊情况下。 1. C .h 文件的基本用途 C 的头文件&#xff08…