news 2026/10/15 11:03:36

python正则表达式实例代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python正则表达式实例代码

前言


正则表达式(regular expression,简称 regex)是处理文本的通用工具:在一堆字符里找出满足某种形状的片段,或者把符合形状的片段替换成别的内容。Python 通过标准库re模块提供这套能力,不需要安装任何第三方包。


初学者最常见的误解有两个。第一,以为re.match()会在整段文字里「到处找」——其实它只从字符串开头尝试匹配,找不找得到都不看后面。第二,以为写了正则就一定比手写字符串处理快——正则有回溯(backtracking)开销,写得不好可能比直接判断还慢,具体差多少要看数据和模式,不能用固定倍数概括。


本文用一批可以直接复制进.py文件运行的实例,把「查找、提取、替换、校验」四类常见需求串起来,并在最后集中列出几个真会踩到的坑。所有示例基于 Python 3.8+ 编写,用到的特性都会标注版本。另外提醒:Python 2.7 已于 2020 年 1 月 1 日停止维护,它在re上按 bytes 语义处理字符串、还需要u"..."前缀来得到 Unicode 字符串,unicode、basestring类型在 Python 3 里也已不存在,旧教程的写法不要照搬。


一、最常用的四个动作


re模块的模块级函数(module-level function)是四个动作最直接的写法:




动作函数返回值说明



找第一个re.search(pattern, string)Match或None扫描整串,任意位置命中即可

从开头匹配re.match(pattern, string)Match或None只从下标 0 开始

找全部re.findall(pattern, string)列表返回所有不重叠匹配的文本

替换re.sub(pattern, repl, string)新字符串原字符串不变,返回新串



用一句话记住match和search的区别:re.match("c", "abcdef")返回None,而re.search("c", "abcdef")返回一个Match对象(官方文档的search() vs. match()一节给的就是这个例子)。要在「整串完全符合」时才成功,还可以用re.fullmatch(),它需要 Python 3.4 及以上。


下面的实例覆盖手机号、邮箱、日期、中文和空白折叠:


# 适用于 Python 3.8+
import re

text = "联系邮箱:alice@example.com,手机 13800138000,备用 010-88886666"

# 找所有邮箱地址
emails = re.findall(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", text)
print(emails) # ['alice@example.com']

# 找所有 11 位手机号:1 开头,第二位 3-9,后面再跟 9 位数字
phones = re.findall(r"1[3-9]\d{9}", text)
print(phones) # ['13800138000']

# 把空白字符折叠成单个空格
collapsed = re.sub(r"\s+", " ", text)
print(collapsed)

\d在默认的 Unicode(str)模式下匹配「任意 Unicode 十进制数字」,范围比[0-9]大;在 bytes 模式或加了re.ASCII时才等价于[0-9]。上面的字符串里只有 ASCII 数字,所以\d和[0-9]结果一样,但换成含全角数字的文本时两者就会分叉。


二、分组:把一次匹配拆成几块


圆括号(...)表示一个捕获组(capturing group),匹配完成后可以用Match.group()按序号或名字取出每一段。


# 适用于 Python 3.8+
import re

line = "2024-05-01 上线,2024-06-15 回滚"
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", line)
if m:
print(m.group(0)) # 2024-05-01,整个匹配
print(m.group(1)) # 2024,第一个括号
print(m.group(2)) # 05
print(m.group(3)) # 01
print(m.groups()) # ('2024', '05', '01')
print(m.span()) # (0, 10),匹配在原串里的起止下标

Match.span()返回(start, end)二元组,m.group()等价于m.group(0)。除此之外还有两个常用方法:



  • m.groups(default=None):返回从第 1 组到最后一组的元组,没参与匹配的组用default填充。

  • m.groupdict(default=None):只针对命名组,返回「名字到内容」的字典。命名组用(?P<name>...)写法,例如(?P<year>\d{4})。


findall对分组很敏感:没有分组时返回整段匹配文本,只有一个分组时返回该分组的内容,有多个分组时返回元组。所以想拿「整段」就一定不要随便加括号,或者改用finditer逐个处理Match对象。


# 适用于 Python 3.8+
import re

src = "宽度=20 高度=10"
print(re.findall(r"\w+=\d+", src)) # ['宽度=20', '高度=10'],无分组
print(re.findall(r"(\w+)=(\d+)", src)) # [('宽度', '20'), ('高度', '10')]

# 想要每段匹配的起止位置,用 finditer
for m in re.finditer(r"(\w+)=(\d+)", src):
print(m.group(1), m.group(2), m.span())

三、替换:字符串或函数都行


re.sub(pattern, repl, string, count=0)的repl既可以是字符串,也可以是函数。是字符串时,\1、\g<name>这类反向引用(backreference)会被替换成对应分组的内容;是函数时,函数接收一个Match对象,返回什么就替换成什么。count=0(默认)表示全部替换,正数表示最多替换几次。


# 适用于 Python 3.8+
import re

text = "手机 13800138000 与 13912345678 都已登记"

# repl 用函数:把中间四位打码
def mask(m):
s = m.group(0)
return s[:3] + "****" + s[-4:]

print(re.sub(r"1[3-9]\d{9}", mask, text))
# 手机 138****8000 与 139****5678 都已登记

# repl 用字符串 + 反向引用:交换键值对顺序
kv = "name:alice"
print(re.sub(r"(\w+):(\w+)", r"\2:\1", kv)) # alice:name

如果替换内容来自用户输入、本身可能含反斜杠,不要把它直接当repl用;re.escape()是为「模式」转义的,不能用在替换串上。稳妥做法是把替换逻辑写成函数,返回原样的字符串,避免\1之类被误解释。


四、提取中文与清洗


中文字符在 Unicode 里的基本区间是一到鿿(CJK 统一表意文字),配合+可以连续取出中文片段:


# 适用于 Python 3.8+
import re

s = "品牌:华为 Mate60 Pro,产地:中国深圳"
print(re.findall(r"[一-鿿]+", s)) # ['品牌', '华为', '产地', '中国深圳']

# 只保留字母、数字和下划线,去掉其它符号
raw = "a b!c#d$e%f^g&h*i"
print(re.sub(r"[^0-9A-Za-z_]", "", raw)) # abcdefghi

第二个例子用「取反」字符集[^...]表达「除了这些都不要」,是清洗文本的常用套路。注意^只有在方括号内的第一个位置才表示取反;放在别处它就是普通的^字符。


常见坑点



  1. ❌ 用re.match()在长文本里找任意位置的内容,结果永远None。


✅ 从任意位置找用re.search();只在开头找才用re.match()。



  1. ❌ 写re.findall("(abc)", s)却发现返回的是['abc']这种分组内容、以为拿错了。


✅ 记住findall有分组时返回分组;要整段匹配就删掉多余的括号,或改用re.finditer()。



  1. ❌ 模式里写"\d+"而不是r"\d+",在含\1、\b等序列时被 Python 字符串先解释一遍,行为诡异。


✅ 正则模式一律加r前缀写成r"\d+",让反斜杠原样交给re。



  1. ❌ 以为.能匹配换行,用r".+"去匹配多行文本却只拿到第一行。


✅ 默认.不匹配换行;需要时加re.DOTALL(也可写成(?s))。



  1. ❌ 用贪心的r"<li>(.*)</li>"去提取多个列表项,结果一次吞掉了从第一个<li>到最后一个</li>的整块。


✅ 改成懒惰的r"<li>(.*?)</li>",量词加?后「尽量少匹配」。



  1. ❌ 用r"[0-9]+"与r"\d+"混着写,却期待它们在含全角数字的文本里得到同样结果。


✅ 默认 Unicode 模式下\d比[0-9]范围大;要限定 ASCII 就写[0-9]或加re.ASCII。



  1. ❌ 用re.split(r"(\W+)", s)后,发现结果列表里多出了分隔符本身。


✅ 这是文档规定的行为:分隔模式里若有捕获组,分组内容会一并保留在结果中;不想要就写成非捕获组(?:...)。



  1. ❌ 把手机号、身份证这类正则在整段文本上直接findall,忽略了它还会匹配到更长的数字串中间一段。


✅ 用\b或(?<!\d)、(?!\d)之类的边界断言把前后卡住,避免「切到别人一半」。


总结




需求推荐函数关键点



从任意位置找第一个re.search命中即返回Match,否则None

判断整串是否符合re.fullmatch需 Python 3.4+

取全部分段re.finditer+group()比findall更好控制分组

替换re.subrepl可为字符串或函数

按模式切分re.split捕获组会保留在结果里



把「找、取、换、切」四类动作对应到search、finditer、sub、split,再牢记模式用r"..."、match只从开头、.不跨行,大部分日常文本处理就能写对。真要抠性能,请用timeit在自己的数据上实测,而不是相信某个固定的「提速几倍」说法。




版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 11:03:28

Python构建网页爬虫原理分析

前言 「会用 requests 抓一个页面」和「理解爬虫原理」是两回事。前者是调库&#xff0c;后者是能回答&#xff1a;一次请求到拿到正文之间经历了什么、下一页地址是从哪里发现的、怎么保证同一页面不被抓两遍、循环靠什么终止。这四个问题答不上来&#xff0c;遇到稍微复杂一点…

作者头像 李华
网站建设 2026/10/15 11:03:20

TCP流量控制与拥塞控制的本质区别与协同机制

1. 为什么“流量控制”和“拥塞控制”总被混为一谈&#xff1f;——从一个真实丢包现场说起上周帮某高校实验室调试一套实时视频流分析系统&#xff0c;后端用的是自研的TCP长连接传输模块。现象很典型&#xff1a;局域网内一切正常&#xff0c;一旦接入校园骨干网&#xff0c;…

作者头像 李华
网站建设 2026/10/15 11:03:19

期刊要求披露AI使用吗?投稿前AIGC率多少才稳妥?

期刊AI率超标被退稿&#xff0c;往往不是因为作者用了AI&#xff0c;而是投稿前根本没查过。 自己写的论文同样可能有AI率&#xff0c;20%-30%的情况并不少&#xff0c;尤其是综述和总结部分&#xff0c;表达越规整越容易被误判为AIGC生成。 每个期刊的AIGC率要求是多少&…

作者头像 李华
网站建设 2026/10/15 11:03:17

从感知机到神经网络:激活函数如何突破线性不可分困境

某天下午我在调一个实验代码&#xff0c;用单层感知机去学 XOR&#xff08;异或&#xff09;逻辑&#xff0c;折腾了一整个晚上&#xff0c;训练准确率始终卡在 75% 左右&#xff0c;四组样本里总有那么一组会学错。那一刻我突然意识到&#xff1a;教科书里说的“线性不可分”根…

作者头像 李华
网站建设 2026/10/15 11:03:04

ArcGIS协同克里金法实战:从互协方差建模到交叉验证避坑指南

简介&#xff1a;这份ArcGIS教程文档面向地理信息、环境科学与资源管理领域的学习者与从业者&#xff0c;系统讲解协同克里金法这一空间插值技术。内容围绕如何利用目标变量Z1的自相关性及其与协变量Z2、Z3之间的互相关性提升预测精度展开&#xff0c;涵盖普通协同克里金法的模…

作者头像 李华
网站建设 2026/10/15 11:03:02

TCP流量控制与拥塞控制协同机制深度解析

1. 为什么TCP的流量控制和拥塞控制不是“背下来就行”的知识点&#xff1f;你翻过《计算机网络》教材&#xff0c;肯定见过滑动窗口、慢启动、拥塞避免这些词——但合上书&#xff0c;真让你在Wireshark里抓包分析一段视频会议卡顿的根源&#xff0c;或者调试一个高延迟API接口…

作者头像 李华