正则表达式之捕获分组——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),优先考虑专用解析器。


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

相关推荐
aiguangyuan17 分钟前
使用LSTM进行情感分类:原理与实现剖析
人工智能·python·nlp
小小张说故事25 分钟前
BeautifulSoup:Python网页解析的优雅利器
后端·爬虫·python
luoluoal26 分钟前
基于python的医疗领域用户问答的意图识别算法研究(源码+文档)
python
Shi_haoliu32 分钟前
python安装操作流程-FastAPI + PostgreSQL简单流程
python·postgresql·fastapi
ZH154558913141 分钟前
Flutter for OpenHarmony Python学习助手实战:API接口开发的实现
python·学习·flutter
小宋102143 分钟前
Java 项目结构 vs Python 项目结构:如何快速搭一个可跑项目
java·开发语言·python
一晌小贪欢1 小时前
Python 爬虫进阶:如何利用反射机制破解常见反爬策略
开发语言·爬虫·python·python爬虫·数据爬虫·爬虫python
躺平大鹅1 小时前
5个实用Python小脚本,新手也能轻松实现(附完整代码)
python
yukai080082 小时前
【最后203篇系列】039 JWT使用
python