python的正则表达式-re模块(Base Python 3.14)
正则表达式(Regular expressions,也叫 REs、 regexs 或 regex patterns),本质上是嵌入 Python 内部并通过 re 模块提供的一种微小的、高度专业化的编程语言。使用这种小语言,你可以为想要匹配的可能字符串编写规则;这些字符串可能是英文句子、邮箱地址、TeX 命令或任何你喜欢的内容。然后,你可以提出诸如“此字符串是否与表达式匹配?”、“字符串中是否存在表达式的匹配项?”之类的问题。你还可以用正则来修改字符串,或以各种方式将其拆分。
正则表达式会被编译成一系列字节码,然后由 C 语言编写的匹配引擎执行。对于高级用途,可能有必要特别注意引擎将如何执行一个给定的正则,并以某种方式写入正则,以生成运行更快的字节码。本文不涉及优化问题,因为这要求你对正则引擎的匹配过程有很好的了解。
正则表达式语言相对较小且受限,因此并非所有可能的字符串处理任务都可以使用正则表达式完成。有些任务尽管 可以 用正则表达式来完成,但表达式会变得非常复杂。 这些情况下,最好通过编写 Python 代码来进行处理。 也许 Python 代码会比精心设计的正则表达式慢,但它可能更容易理解。
正则表达式是一种小型、专用的语言,用来匹配字符串模式。可以用它做三件事:
-
判断字符串是否符合模式
-
查找字符串中符合模式的部分
-
替换、拆分字符串
1:基本字符匹配
-
普通字符匹配自身,例如
'test'匹配字符串'test'。 -
元字符(特殊字符,不直接匹配自身,这些是比较特殊的字符,用于控制匹配的模式):
#有点多,看一遍感觉就行了😀 . ^ $ * + ? { } [ ] \ | ( ) . (点号) 匹配除换行符(\n)外的任意单个字符(re.DOTALL 可以匹配换行符) 示例:a.b 匹配 "aab", "a1b", "a b" 等 ^ (脱字符) 匹配字符串的开始位置 示例:^abc 匹配以 "abc" 开头的字符串 $ (美元符) 匹配字符串的结束位置 示例:xyz$ 匹配以 "xyz" 结尾的字符串 \ (反斜杠) 转义字符,使后面的字符失去特殊含义 示例:\. 匹配实际的点号而不是任意字符 [] (方括号) 定义字符集合,匹配其中任意一个字符 示例:[aeiou] 匹配任意一个元音字母 [^] (否定字符类) 匹配不在方括号中的任意字符 示例:[^0-9] 匹配任意非数字字符 - (连字符) 在字符类中表示范围 示例:[a-z] 匹配任意小写字母 * (星号) 匹配前面的子表达式(字符)零次或多次 示例:ab*c 匹配 "ac", "abc", "abbc" 等 + (加号) 匹配前面的子表达(字符)式一次或多次 示例:ab+c 匹配 "abc", "abbc" 但不匹配 "ac" ? (问号) 匹配前面的子表达式零次或一次 示例:colou?r 匹配 "color" 和 "colour" {n} (花括号) 精确匹配n次 示例:a{3} 匹配 "aaa" {n,} 至少匹配n次 示例:a{2,} 匹配 "aa", "aaa" 等 {n,m} 匹配n到m次 示例:a{2,4} 匹配 "aa", "aaa", "aaaa" () (圆括号) 定义子表达式或捕获组 示例:(ab)+ 匹配 "ab", "abab" 等 | (竖线) 表示"或"关系 示例:cat|dog 匹配 "cat" 或 "dog" \d 匹配任意数字,等价于 [0-9] \D(大写) 匹配任意非数字,等价于 [^0-9] \w 匹配任意单词字符(字母、数字、下划线),等价于 [a-zA-Z0-9_] \W(大写) 匹配任意非单词字符,等价于 [^a-zA-Z0-9_] \s 匹配任意空白字符(空格、制表符、换行符等) \S(大写) 匹配任意非空白字符 \b 匹配单词边界 示例:\bcat\b 匹配 "cat" 但不匹配 "category" \B 匹配非单词边界(也就是这是个词中的一个片段) 示例:\Bcat\B 匹配 "scattered" 中的 "cat" 但不匹配单独的 "cat" \n 匹配换行符 \t 匹配制表符 \r 匹配回车符 \f 匹配换页符 \v 匹配垂直制表符 #默认情况下,量词(*, +, ?, {})是贪婪的,会尽可能多地匹配字符。在量词后加?可使其变为非贪婪(懒惰)模式: *?:零次或多次,但尽可能少 +?:一次或多次,但尽可能少 ??:零次或一次,但尽可能少 {n,m}?:n到m次,但尽可能少 示例:<.*?> 匹配HTML标签时不会跨标签匹配 (?=...) (正向肯定预查) 匹配后面跟着特定模式的位置 示例:Windows(?=95|98) 匹配后面跟着95或98的"Windows" (?!...) (正向否定预查) 匹配后面不跟着特定模式的位置 示例:Windows(?!95|98) 匹配后面不跟着95或98的"Windows" (?<=...) (反向肯定预查) 匹配前面是特定模式的位置 示例:(?<=95|98)Windows 匹配前面是95或98的"Windows" (?<!...) (反向否定预查) 匹配前面不是特定模式的位置 示例:(?<!95|98)Windows 匹配前面不是95或98的"Windows"
2:Python中使用正则
re模块是python自带的模块,不需要额外的安装。先看一下都有哪些用法,掌握一些必要的核心的函数。
| 函数名 | 作用 | 参数及含义 | 返回值 |
|---|---|---|---|
re.match(pattern, string, flags=0) |
从字符串开头匹配正则表达式 | - pattern:正则表达式 - string:目标字符串 - flags(可选):匹配模式,如 re.I, re.M, re.S |
匹配成功:Match 对象 匹配失败:None |
re.search(pattern, string, flags=0) |
在整个字符串中搜索第一个匹配项 | 与 re.match 相同 |
匹配成功:Match 对象 匹配失败:None |
re.findall(pattern, string, flags=0) |
返回字符串中所有匹配项 | 与 re.match 相同 |
列表,包含所有匹配子串; 无匹配返回 [] |
re.finditer(pattern, string, flags=0) |
返回字符串中所有匹配项的迭代器 | 与 re.match 相同 |
迭代器,每个元素是 Match 对象; 无匹配迭代为空 |
re.split(pattern, string, maxsplit=0, flags=0) |
根据正则表达式分割字符串 | - pattern:正则表达式 - string:目标字符串 - maxsplit(可选):最大分割次数,0 表示不限 - flags(可选):匹配模式 |
列表,包含分割后的子串 |
re.sub(pattern, repl, string, count=0, flags=0) |
使用 repl 替换匹配部分 |
- pattern:正则表达式 - repl:替换字符串或函数 - string:目标字符串 - count(可选):替换次数,0 表示全部 - flags(可选):匹配模式 |
返回替换后的新字符串 |
re.subn(pattern, repl, string, count=0, flags=0) |
与 re.sub 类似,但返回替换次数 |
参数与 re.sub 相同 |
返回 (new_string, 替换次数) 的元组 |
re.compile(pattern, flags=0) |
编译正则表达式,生成 Pattern 对象 |
- pattern:正则表达式 - flags(可选):匹配模式 |
返回 Pattern 对象,可调用 .match(), .search(), .findall(), .split(), .sub() |
匹配模式:
匹配模式(flags) 作用 示例 说明 re.I或re.IGNORECASE忽略大小写匹配 re.match(r'abc', 'ABC', re.I)→ 匹配成功'a'可以匹配'A're.M或re.MULTILINE多行模式: ^和$匹配每一行的开头和结尾re.findall(r'^a', 'a\nb\na', re.M)→['a', 'a']默认情况下, ^和$只匹配整个字符串的开头和结尾re.S或re.DOTALL使 .匹配换行符\nre.findall(r'.+', 'a\nb', re.S)→['a\nb']默认情况下, .不匹配换行符re.X或re.VERBOSE允许正则表达式写成多行并加注释 re.compile(r""" \d+ # 匹配数字 """, re.X)便于阅读复杂正则表达式 re.A或re.ASCII只匹配 ASCII 字符, \w,\b等只匹配 ASCIIre.findall(r'\w+', 'café', re.A)→['caf']非 ASCII 字符(如 'é')不会匹配re.L或re.LOCALE依赖当前区域设置的字符分类 根据系统 locale 对字符分类处理 一般不常用,依赖操作系统语言环境 re.U或re.UNICODE以 Unicode 方式匹配 \w,\b等默认 Python3 已开启 在 Python3 默认启用 Unicode 支持 re.T匹配方式不常用(弃用) — 现代 Python 中一般不用 flags=0 表示没有启用任何模式 默认匹配:区分大小写, .不匹配换行符,^和$匹配整个字符串开头和结尾,不启用多行、多行注释或其他特殊行为
| 方法 | 参数 | 作用 | 详细说明 |
|---|---|---|---|
group([n]) |
n 可选,整数或多个整数 |
返回匹配的子串或指定捕获组 | - 如果不传 n,返回整个匹配字符串,即正则匹配的完整内容 - 如果传 n,返回第 n 个捕获组(从 1 开始,0 是整个匹配) - 可以传多个参数,如 m.group(1,2) 返回一个元组 |
groups(default=None) |
default 可选,默认 None |
返回所有捕获组组成的元组 | - 捕获组就是正则中用 () 包起来的部分 - 返回的顺序和正则里括号的顺序一致 - 如果某个捕获组没有匹配,则返回 default |
groupdict(default=None) |
default 可选,默认 None |
返回命名捕获组组成的字典 | - 捕获组如果使用 (?P<name>...) 命名,则可以通过字典获取 - 没匹配到的组会返回 `default |
start([group]) |
group 可选,整数 |
返回匹配或捕获组的起始索引(字符串位置) | - 索引从 0 开始 - 默认返回整个匹配的起始位置 - 如果传 group,返回该捕获组在原字符串的起始位置 |
end([group]) |
group 可选,整数 |
返回匹配或捕获组的结束索引(不包括该位置字符) | - 结束索引是 右开区间,即不包含该位置 - 默认返回整个匹配的结束位置 - 如果传 group,返回该捕获组结束位置 |
span([group]) |
group 可选,整数 |
返回 (start, end) 元组 |
- 其实就是同时返回 start() 和 end() - 默认返回整个匹配的区间 - 如果传 group,返回该捕获组的区间 |
import re
# 示例字符串
text = "abc123"
# 正则里有两个捕获组:
# 第一个 (\w+) 代表匹配字母部分
# 第二个 (\d+) 代表匹配数字部分
m = re.match(r'(\w+)(\d+)', text)
# =====================================================
# 1️⃣ group([n]):返回匹配的子串或指定捕获组
# =====================================================
# 不传参数,返回整个匹配到的内容
print("m.group() ->", m.group()) # 'abc123'
# group(0) 永远是整个匹配结果(等价于不传参数)
print("m.group(0) ->", m.group(0)) # 'abc123'
# group(1) 返回第1个捕获组(第一个括号)
print("m.group(1) ->", m.group(1)) # 'abc'
# group(2) 返回第2个捕获组(第二个括号)
print("m.group(2) ->", m.group(2)) # '123'
# 可以一次取多个捕获组,返回元组
print("m.group(1, 2) ->", m.group(1, 2)) # ('abc', '123')
# =====================================================
# 2️⃣ groups(default=None):返回所有捕获组的元组
# =====================================================
m2 = re.match(r'(\w+)(\d+)?', "abc") # 第二组是可选的 '?'
print("\nm2.groups() ->", m2.groups())
# 输出 ('abc', None),因为第二个捕获组 (\d+) 没匹配到
print("m2.groups(default='0') ->", m2.groups(default='0'))
# 输出 ('abc', '0'),用 default 替换 None
# =====================================================
# 3️⃣ groupdict(default=None):返回命名捕获组的字典
# =====================================================
# 使用 (?P<name>...) 定义命名捕获组
m3 = re.match(r'(?P<word>\w+)(?P<num>\d+)?', "abc")
print("\nm3.groupdict() ->", m3.groupdict())
# {'word': 'abc', 'num': None}
print("m3.groupdict(default='0') ->", m3.groupdict(default='0'))
# {'word': 'abc', 'num': '0'}
# 命名捕获组还可以直接通过 group('name') 访问
print("m3.group('word') ->", m3.group('word')) # 'abc'
# =====================================================
# 4️⃣ start([group]):返回匹配或捕获组的起始索引
# =====================================================
print("\nm.start() ->", m.start()) # 0,整个匹配的起始位置
print("m.start(1) ->", m.start(1)) # 0,第1组 'abc' 的起始
print("m.start(2) ->", m.start(2)) # 3,第2组 '123' 的起始
# =====================================================
# 5️⃣ end([group]):返回匹配或捕获组的结束索引(不含该位置)
# =====================================================
print("\nm.end() ->", m.end()) # 6,整个匹配结束位置
print("m.end(1) ->", m.end(1)) # 3,第1组 'abc' 结束
print("m.end(2) ->", m.end(2)) # 6,第2组 '123' 结束
# =====================================================
# 6️⃣ span([group]):返回 (start, end) 元组
# =====================================================
print("\nm.span() ->", m.span()) # (0, 6),整个匹配区间
print("m.span(1) ->", m.span(1)) # (0, 3),第1组区间
print("m.span(2) ->", m.span(2)) # (3, 6),第2组区间
# 你可以用 span 结果在原字符串中切片取出对应部分
start, end = m.span(1)
print("text[start:end] ->", text[start:end]) # 'abc'
有了上边的“字典”就可以开始使用正则表达式了。上手试试。
1. re.match()-从头匹配
import re
text = "python is great"
m = re.match(r"python", text)
if m: #在这里,当匹配的时候,如果匹配的是空那么是会返回None的。因此这里就是匹配是否是空,如果不是空(也就是True)
print(m.group()) #返回匹配的子串或指定捕获组
print(m.span()) #返回start end 的元组。
#python
#(0, 6)
2.re.search()-找第一个匹配的
import re
text1 = "i love python and python"
m = re.search(r"python", text1, re.IGNORECASE)
print(m.group())
print(m.start(), m.end())
#python
#7 13
3.re.findall() - 找所有匹配(返回列表)
text2 = "Emails: alice@163.com, bob@gmail.com, eve@outlook.com"
email = re.findall(r'\w+@\w+\.\w+', text2) #\w匹配任意单词字符(字母、数字、下划线)
#\w+匹配一个或多个“单词字符” (字母、数字、下划线)
print(email)
4.re.finditer() —— 迭代器版 findall(带位置)
for m in re.finditer(r'\d+', "age:18, score:95, id:007"):
print(f"找到数字:{m.group()}在位置{m.span()}")
#找到数字:18在位置(4, 6)
#找到数字:95在位置(14, 16)
#找到数字:007在位置(21, 24)
5.re.sub() —— 替换
text3 = "my phone is 123-123-4256"
clean = re.sub(r'\d{3}-\d{3}-\d{4}','[PHONE]', text3) #\d{} 匹配数字
#re.sub(pattern, repl, string, count=0, flags=0) 在字符串 string 中查找所有匹配 pattern 的部分,并把它们替换为 repl。。
print(clean)
6.re.split() —— 正则分割
text4 = "apple, banban; orange grape"
items = re.split(r'[,;]\s*', text4) #[,;]\s* 一个逗号或分号,后面可带任意数量的空格
#re.split(pattern, string, maxsplit=0, flags=0)--按正则匹配的内容来切割字符串,返回一个列表。
print(items)
#['apple', 'banban', 'orange grape']
7.re.compile() —— 预编译-不用每次在从新写正则表达式了
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
dates = ["2025-11-12", "invalid", "2066-01-01"]
for s in dates:
if pattern.match(s):
print(s,"是合法的日期格式")
#2025-11-12 是合法的日期格式
#2066-01-01 是合法的日期格式
ending - 感觉够用了,遇到再麻烦的话就直接上大模型了。
更多推荐



所有评论(0)