Python3 正则表达式之正则表达式模式详解
Python3 正则表达式之正则表达式模式详解
🎯 学习目标
深入理解 Python 正则表达式中的各种模式匹配语法,掌握元字符、量词、分组、断言等高级用法。能够在复杂文本处理任务中编写高效、准确的正则表达式,并具备调试和优化正则表达式的能力。
🔑 核心重点
| 分类 | 内容 |
|---|---|
| 元字符 | .、^、` |
| -------------- | ------------------------------------------------------------ |
、\d、\w、\s 等 |
|
| 量词 | *、+、?、{n,m} 控制重复次数 |
| 分组与捕获 | ( ) 捕获分组、(?: ) 非捕获分组、(?P<name>...) 命名分组 |
| 断言 | (?=...) 正向肯定查找、(?!...) 正向否定查找 |
| 贪婪 vs 非贪婪 | 默认贪婪匹配,使用 ? 变为非贪婪 |
| 编译模式 | 使用 re.compile() 提高效率,支持标志位(如 re.IGNORECASE) |
📚 详细讲解
一、元字符:基础匹配单位
元字符用于表示某一类字符或特殊含义。
| 元字符 | 含义 | 示例 |
|---|---|---|
. |
匹配任意单个字符(换行除外) | r'.at' 匹配 cat、hat、bat 等 |
\d |
数字 [0-9] | r'\d+' 匹配连续数字 |
\D |
非数字 | r'\D+' 匹配非数字字符串 |
\w |
单词字符 [a-zA-Z0-9_] | r'\w+' 匹配标识符、变量名等 |
\W |
非单词字符 | r'\W+' 匹配标点、空格等 |
\s |
空白字符(空格、tab、换行) | r'\s+' 匹配任意空白 |
\S |
非空白字符 | r'\S+' 匹配非空白内容 |
\b |
单词边界 | r'\bcat\b' 匹配完整单词 "cat" |
\B |
非单词边界 | r'\Bcat\B' 匹配 "category" 中的 cat |
✅ 示例:
import re
text = "abc123xyz"
pattern = r'\d+' # 匹配所有数字
print(re.findall(pattern, text)) # 输出: ['123']
二、量词:控制重复次数
| 量词 | 含义 | 示例 |
|---|---|---|
* |
0 次或多次 | r'a*' 匹配 ""、"a"、"aa" 等 |
+ |
至少 1 次 | r'\d+' 匹配至少一个数字 |
? |
0 或 1 次 | r'file-?\d+' 匹配 file123 或 file-123 |
{n} |
精确 n 次 | r'\d{3}' 匹配三位数字 |
{n,} |
至少 n 次 | r'\w{5,}' 匹配长度 ≥5 的单词 |
{n,m} |
n 到 m 次 | r'[A-Z]{2,4}' 匹配 2~4 个大写字母 |
✅ 示例:
text = "abc a123 defg"
pattern = r'\w{3,5}' # 匹配长度为 3~5 的单词
print(re.findall(pattern, text)) # 输出: ['abc', 'a123', 'defg']
三、分组与命名捕获
| 分组形式 | 用途说明 |
|---|---|
(pattern) |
捕获分组,结果会保存在 group() 中 |
(?:pattern) |
非捕获分组,不保存匹配结果 |
(?P<name>...) |
命名捕获分组,可通过名称访问匹配内容 |
(?P=name) |
引用之前定义的命名组 |
✅ 示例:
text = "John Doe <john@example.com>"
pattern = r'(?P<name>\w+) (?P<lastname>\w+) <(?P<email>[^>]+)>'
match = re.search(pattern, text)
if match:
print("Name:", match.group('name')) # John
print("Email:", match.group('email')) # john@example.com
四、断言:条件匹配
| 表达式 | 含义 |
|---|---|
(?=pattern) |
正向肯定预查:后面是 pattern |
(?!pattern) |
正向否定预查:后面不是 pattern |
(?<=pattern) |
反向肯定预查:前面是 pattern |
(?<!pattern) |
反向否定预查:前面不是 pattern |
✅ 示例:提取价格前带美元符号的数字
text = "$100, $200, ¥300"
pattern = r'\$(?=\d+)'
matches = re.findall(pattern, text)
print(matches) # 输出: ['$'] (只匹配 $ 后面有数字的情况)
五、贪婪 vs 非贪婪匹配
默认情况下,正则表达式是“贪婪匹配”,即尽可能多地匹配内容。使用 ? 可以变为“非贪婪匹配”。
✅ 示例:
text = "<div>Hello</div><span>World</span>"
# 贪婪匹配
pattern_greedy = r'<.*>'
print(re.findall(pattern_greedy, text))
# 输出: ['<div>Hello</div><span>World</span>']
# 非贪婪匹配
pattern_lazy = r'<.*?>'
print(re.findall(pattern_lazy, text))
# 输出: ['<div>', '</div>', '<span>', '</span>']
六、编译模式与标志位
| 标志位 | 功能说明 |
|---|---|
re.IGNORECASE (I) |
忽略大小写匹配 |
re.MULTILINE (M) |
多行模式,^ 和 ` |
| --------------------- | --------------------------------------- |
re.IGNORECASE (I) |
忽略大小写匹配 |
| 匹配每行开头和结尾 | |
re.DOTALL (S) |
. 匹配包括换行在内的所有字符 |
re.VERBOSE (X) |
支持注释和空白,便于阅读长正则 |
✅ 示例:
text = "Hello\nWorld"
pattern = re.compile(r'^world', re.IGNORECASE | re.MULTILINE)
matches = pattern.findall(text)
print(matches) # 输出: ['World']
⚠️ 注意事项
- 尽量避免使用过于复杂的正则表达式,影响可读性和性能。
- 使用
re.escape()对用户输入进行转义,防止正则注入攻击。 - 在 PyCharm 中可以使用
Find in Path+Regex模式快速测试正则。 - 正则表达式匹配失败时返回
None,务必做判断处理。 - 使用命名分组提升代码可读性,尤其在提取结构化数据时。
🧪 实际案例分析
📌 场景:提取 HTML 中所有的超链接和锚文本
示例代码:
import re
html = '''
<p>这是第一个链接:<a href="https://example.com">示例网站</a></p>
<p>另一个链接:<a href="http://test.org">测试站点</a></p>
'''
# 匹配 <a> 标签并提取 href 和锚文本
pattern = r'<a\s+href=["\'](.*?)["\'].*?>(.*?)</a>'
links = re.findall(pattern, html, re.DOTALL)
for href, text in links:
print(f"链接: {href}, 文本: {text.strip()}")
📌 输出:
链接: https://example.com, 文本: 示例网站
链接: http://test.org, 文本: 测试站点
📌 说明:
- 使用了非贪婪匹配
.*?来精确提取内容。 - 使用
re.DOTALL让.匹配换行符,适用于多行 HTML。 - 使用分组分别提取
href和锚文本。
🧩 拓展练习(动手实践)
- 编写正则表达式提取一段文本中所有合法的电子邮件地址。
- 编写程序识别一段文本中的 IP 地址(IPv4),并验证其格式是否正确。
- 编写脚本从一段日志中提取 HTTP 请求状态码(如 200、404、500)并统计出现频率。
- 编写函数将一段中文文本中的日期格式统一转换为
YYYY-MM-DD格式(如“2025年6月3日” → “2025-06-03”)。 - 编写程序从 JSON 字符串中提取所有的键名(key)。
如果你希望我为你提供:
- 《Python 正则表达式模式速查表 PDF》
- 更多实战项目练习题(含解析)
- 视频教学资源推荐(中文讲解)
- 如何结合 PyCharm 快捷键快速调试正则表达式
欢迎随时告诉我 😊

浙公网安备 33010602011771号