正则表达式之捕获分组——Python篇

简介

在处理文本数据时,正则表达式(Regular Expressions)是 Python 中一个极其强大的工具。而 捕获分组(Capturing Groups) 则是正则表达式中用于提取特定信息的核心机制之一。本文将深入讲解 Python 中如何使用捕获分组,并通过示例帮助你掌握其用法。

什么是捕获分组?

捕获分组是通过圆括号 () 将正则表达式的一部分"包裹"起来,从而 将匹配到的子字符串单独提取出来 。每个括号定义一个分组,Python 的 re 模块会按顺序为这些分组编号(从 1 开始),并允许你在匹配结果中访问它们。

基本语法

python 复制代码
import re

pattern = r'(\d{4})-(\d{2})-(\d{2})'  # 匹配 YYYY-MM-DD 格式的日期
text = '今天是 2026-01-14'

match = re.search(pattern, text)
if match:
    print("完整匹配:", match.group(0))   # 整个匹配内容
    print("年份:", match.group(1))       # 第1个分组:年
    print("月份:", match.group(2))       # 第2个分组:月
    print("日期:", match.group(3))       # 第3个分组:日

输出:

output 复制代码
完整匹配: 2026-01-14
年份: 2026
月份: 01
日期: 14

注意group(0) 表示整个匹配的字符串,而 group(1)group(2) 等表示各个捕获分组的内容。


多个匹配与 findall

当你使用 re.findall() 时,行为会根据是否存在捕获分组而有所不同:

  • 没有分组:返回所有完整匹配的字符串列表。
  • 有分组 :返回每个匹配中分组内容组成的元组列表(如果只有一个分组,则返回字符串列表)。
python 复制代码
text = "日期:2025-12-01 和 2026-01-14"

# 无分组
print(re.findall(r'\d{4}-\d{2}-\d{2}', text))
# 输出: ['2025-12-01', '2026-01-14']

# 有分组
print(re.findall(r'(\d{4})-(\d{2})-(\d{2})', text))
# 输出: [('2025', '12', '01'), ('2026', '01', '14')]

命名捕获分组(Named Groups)

除了按位置编号,还可以为分组 命名,使代码更具可读性:

python 复制代码
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
match = re.search(pattern, '2026-01-14')

if match:
    print("年份:", match.group('year'))
    print("月份:", match.group('month'))
    print("日期:", match.group('day'))
    
    # 也可以通过 groupdict() 获取所有命名分组的字典
    print("全部字段:", match.groupdict())

输出:

output 复制代码
年份: 2026
月份: 01
日期: 14
全部字段: {'year': '2026', 'month': '01', 'day': '14'}

命名分组使用 (?P<name>...) 语法,其中 name 是你自定义的标识符。


非捕获分组(Non-capturing Groups)

有时你只想对正则表达式进行逻辑分组,但 不希望 该部分被单独提取出来。这时可以使用非捕获分组 (?:...)

python 复制代码
pattern = r'(?:https?://)?(www\.\w+\.\w+)'
text = '访问 https://www.example.com 或 www.test.org'

matches = re.findall(pattern, text)
print(matches)  # ['www.example.com', 'www.test.org']

在这个例子中,(?:https?://)? 不会被捕获,只有后面的域名部分被捕获。


实战示例:解析日志行

假设你有一行 Web 服务器日志:

log 复制代码
127.0.0.1 - - [14/Jan/2026:09:34:00 +0800] "GET /index.html HTTP/1.1" 200 1234

你可以用捕获分组提取关键信息:

python 复制代码
log_line = '127.0.0.1 - - [14/Jan/2026:09:34:00 +0800] "GET /index.html HTTP/1.1" 200 1234'

pattern = r'''
    (?P\d+\.\d+\.\d+\.\d+)          # IP 地址
    .*?
    $$(?P[^$$]+)$$            # 时间戳
    .*?
    "(?P\w+)\s+(?P[^"]+)"  # 请求方法和路径
    .*?
    (?P\d{3})                    # 状态码
'''

match = re.search(pattern, log_line, re.VERBOSE)
if match:
    info = match.groupdict()
    print(info)

输出(格式化后):

python 复制代码
{
    'ip': '127.0.0.1',
    'timestamp': '14/Jan/2026:09:34:00 +0800',
    'method': 'GET',
    'path': '/index.html HTTP/1.1',
    'status': '200'
}

使用 re.VERBOSE 可以让正则表达式跨多行并添加注释,提高可读性。


小结

  • 捕获分组 (...) 用于提取子匹配内容。
  • 使用 .group(n).group('name') 访问分组。
  • findall() 在有分组时返回分组内容而非完整匹配。
  • 命名分组 (?P<name>...) 提升代码可读性。
  • 非捕获分组 (?:...) 用于逻辑分组但不提取。

📌 提示:正则表达式虽强大,但过度复杂可能降低可维护性。对于结构化数据(如 JSON、XML),优先考虑专用解析器。


自此,本文分享到此结束!!!

相关推荐
战族狼魂2 小时前
Python 完整实现 BCrypt GUI 工具
java·前端·python
小二·2 小时前
Python Web 开发进阶实战:国际化(i18n)与多语言支持 —— Vue I18n + Flask-Babel 全栈解决方案
前端·vue.js·python
小二·2 小时前
Python Web 开发进阶实战:API 安全与 JWT 认证 —— 构建企业级 RESTful 接口
前端·python·安全
Allen_LVyingbo2 小时前
具备安全护栏与版本化证据溯源的python可审计急诊分诊平台复现
开发语言·python·安全·搜索引擎·知识图谱·健康医疗
weixin199701080162 小时前
安家 GO item_get - 获取安家详情数据接口对接全攻略:从入门到精通
java·大数据·python·golang
Wzx1980122 小时前
自研开发的前后端项目部署流程
vue.js·python
洛豳枭薰2 小时前
Java常用开发工具
java·开发语言·python
西红市杰出青年2 小时前
crawl4ai------AsyncPlaywrightCrawlerStrategy使用教程
开发语言·python·架构·正则表达式·pandas
写代码的【黑咖啡】2 小时前
Python 中的 sqlite3 模块:轻量级数据库的完美搭档
数据库·python·sqlite