Python 正则表达式实战:从匹配到分组提取

举报
yd_269685704 发表于 2026/11/07 10:08:13 2026/11/07
【摘要】 Python 正则表达式实战:从匹配到分组提取正则表达式是处理文本的瑞士军刀:校验手机号、提取日志里的关键字段、批量改写文件名,一行模式就能代替几十行字符串操作。本文用实例讲清 Python re 模块最常用的能力。 先跑起来:search、match 与 fullmatchimport retext = "订单号 ORD-20261107,用户 xiao 下单 3 件商品"m = re....

Python 正则表达式实战:从匹配到分组提取

正则表达式是处理文本的瑞士军刀:校验手机号、提取日志里的关键字段、批量改写文件名,一行模式就能代替几十行字符串操作。本文用实例讲清 Python re 模块最常用的能力。

先跑起来:search、match 与 fullmatch

import re

text = "订单号 ORD-20261107,用户 xiao 下单 3 件商品"

m = re.search(r"ORD-\d+", text)
print(m.group())          # ORD-20261107

print(re.match(r"订单", text))      # 从开头匹配,成功
print(re.match(r"用户", text))      # 开头不是"用户",返回 None
print(re.fullmatch(r"\d+", "2026"))  # 整个字符串都要符合,成功

三个函数的区别只在"从哪里开始、到哪里结束":search 全文找第一个,match 只看开头,fullmatch 要求整个字符串都符合。做输入校验时用 fullmatch,做提取时用 search。

分组:一次匹配,取出多个字段

括号就是分组,group(1)、group(2) 按顺序取:

import re

log = "2026-11-07 09:47:33 INFO 用户登录成功"
m = re.search(r"(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+)", log)
print(m.groups())   # ('2026-11-07', '09:47:33', 'INFO')
print(m.group(1))   # 2026-11-07

命名分组可读性更好,适合字段多的场景:

m = re.search(r"(?P<date>\d{4}-\d{2}-\d{2}) (?P<level>\w+)", log)
print(m.groupdict())  # {'date': '2026-11-07', 'level': 'INFO'}

findall 与 finditer:批量提取

text = "价格:12.5 元、8 元、103.2 元"
print(re.findall(r"\d+\.?\d*", text))  # ['12.5', '8', '103.2']

for m in re.finditer(r"(\w+)@(\w+)\.com", "联系 a@huawei.com 或 b@huawei.com"):
    print(m.group(1), "->", m.group(2))

findall 直接给列表,finditer 返回迭代器、能拿到每个匹配的位置,处理大文本时更省内存。

sub:替换与清洗

text = "电话 138-0000-1111,电话 139-2222-3333"
print(re.sub(r"\d{3}-\d{4}-\d{4}", "***********", text))
# 电话 ***********,电话 ***********

# 用分组结果参与替换:把 YYYY-MM-DD 改成 DD/MM/YYYY
date = "今天是 2026-11-07"
print(re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", date))
# 今天是 07/11/2026

sub 的替换串里 \1、\2 引用分组,配合函数还能做动态替换:

def mask(m):
    return m.group(1) + "****" + m.group(2)

print(re.sub(r"(\d{3})\d{4}(\d{4})", mask, "13812345678"))
# 138****5678

预编译:循环里反复用同一个模式

pattern = re.compile(r"\d+")
for line in open("data.txt", encoding="utf-8"):
    if pattern.search(line):
        print(line.strip())

re.compile 把模式编译一次、反复使用,循环里比每次调用 re.search 更快,也更清晰。

容易踩的坑

  • 贪婪匹配:.* 会尽量多吃字符。<div>.*</div> 匹配整段 HTML 时常跨过多个标签,改成非贪婪 <div>.*?</div>。
  • 忘记原始字符串:模式里的 \d 在普通字符串里要写成 "\\d",用 r"\d" 更省心。
  • 点号不匹配换行:. 默认不匹配 \n,跨行匹配加 re.S 标志。
  • 先校验再提取:用户输入先 fullmatch 校验格式,通过后再 search 提取内容用 search,批量提取用 findall/finditer。
  • 分组一次取出多个字段,命名分组让代码自带文档。
  • 清洗脱敏用 sub,高频模式先 compile。
  • 记住贪婪与非贪婪的区别,模式一律写原始字符串。

正则不用背全所有语法,先把这几个函数用熟,日常八成文本处理任务都够用了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。