当前位置: 首页 > news >正文

Python正则表达式完整教程:从入门到实战,解决文本匹配所有难题

一、前言

在日常Python开发、日志解析、爬虫、数据清洗、大模型文本提取场景中,字符串处理是高频需求。普通str内置方法(split/replace/find)只能处理简单固定文本,面对不规则、分段、跨多行、结构化混杂文本时完全无力。

正则表达式(Regular Expression,简称Regex)是一套通用文本匹配规则,Python内置re模块原生支持正则,可实现:格式校验、内容提取、批量替换、文本分割四大核心能力。

本文覆盖完整学习链路:基础语法→re模块六大核心API→标志位(重点解决换行匹配坑)→分组捕获→贪婪/非贪婪→实战案例→高频踩坑总结,全部代码可直接复制运行。

二、前置准备:re模块与原始字符串r""

1. 导入模块

Python标准库自带re,无需额外安装:

importre

2. 必须使用原始字符串 r"正则"

正则大量使用\d\s\.等转义符,普通字符串"\\d"需要双重反斜杠,极易出错;原始字符串r""会忽略Python转义,推荐全程使用。

# 标准写法pattern=r"\d+"# 不推荐,冗余易出错pattern="\\d+"

三、正则核心基础语法

3.1 通用字符匹配(元字符)

符号含义示例
.匹配任意单个字符,默认不匹配换行\nr"a."匹配ab、a9
\d数字 0-9r"\d{11}"匹配手机号
\D非数字匹配字母、符号
\w字母/数字/下划线 a-z A-Z 0-9 _匹配变量名
\W非字母数字下划线匹配空格、逗号
\s空白字符(空格、制表符、换行)匹配任意空白
\S非空白字符匹配可见字符
[]字符集,匹配括号内任意一个[0-9a-z]小写数字
[^]取反,匹配不在括号内字符[^0-9]匹配非数字

3.2 量词:控制匹配重复次数

符号含义
*前面字符匹配 0次或多次
+前面字符匹配 1次或多次(至少1次)
?前面字符匹配 0次或1次
{m}精确匹配m次
{m,n}匹配m~n次

示例:r"\d{6}"匹配6位数字验证码。

3.3 边界锚点:限定匹配位置

符号作用
^字符串开头
$字符串结尾
\b单词边界(字母/数字与符号间隔)

示例:r"^1[3-9]\d{9}$"完整校验11位手机号。

3.4 分组与或逻辑

  1. ():分组,捕获匹配内容,单独提取子片段
  2. |:或,匹配左右任意一个表达式
# 匹配 http 或 httpsr"https?://"# 分组提取年月日r"(\d{4})-(\d{2})-(\d{2})"

四、re模块六大核心API详解

4.1 re.match():仅从字符串开头匹配

只校验文本最开头是否符合规则,中间匹配不到,返回Match对象/None。

text="abc123def"res=re.match(r"\d+",text)print(res)# None,开头不是数字res2=re.match(r"abc",text)print(res2.group())# abc

4.2 re.search():全局搜索第一个匹配项

扫描整个字符串,返回第一个符合规则的内容,最常用单条提取场景。

text="订单号:ORD20260707,金额999"res=re.search(r"\d+",text)print(res.group())# 20260707

4.3 re.findall():提取所有匹配,返回列表(高频)

找出全部匹配子串,无匹配返回空列表,适合批量提取。

text="123 456 789"nums=re.findall(r"\d+",text)print(nums)# ['123', '456', '789']

你之前提取多行JSON代码块使用的就是该方法。

4.4 re.sub():批量替换文本

语法:re.sub(正则, 替换内容, 原文本, count=0),count=0替换全部。

text="价格100,优惠50"new=re.sub(r"\d+","***",text)print(new)# 价格***,优惠***

4.5 re.split():按正则分割字符串

str.split灵活,支持按多种符号分割。

text="苹果,香蕉;橘子 葡萄"parts=re.split(r"[,; ]",text)print(parts)# ['苹果', '香蕉', '橘子', '葡萄']

4.6 re.compile():预编译正则(高复用场景优化)

如果一段正则需要循环调用上千次,提前编译提升性能。

# 预编译pattern=re.compile(r"\d{11}")text_list=["13800138000","test123","13912345678"]fortintext_list:print(pattern.search(t))

五、Match对象取值:group()分组捕获

当正则存在()分组时,可单独提取分组内容:

  • group()/group(0):完整匹配内容
  • group(1):第一个括号分组
  • groups():所有分组组成元组
text="2026-07-07"res=re.search(r"(\d{4})-(\d{2})-(\d{2})",text)print(res.group())# 2026-07-07print(res.group(1))# 2026print(res.groups())# ('2026', '07', '07')

六、正则标志位flags(重点解决换行匹配痛点)

re.match/search/findall都支持flags参数,多个标志用|拼接。

6.1 re.S / re.DOTALL(重中之重)

默认.不能匹配换行符\n,开启后.匹配所有字符(包含换行),解决跨多行文本提取空白问题。

md=""" ```json[{"name":"测试"}]

“”"

不加re.S匹配为空

res = re.findall(r"json(.+?)", md)
print(res) # []

开启跨行匹配

res = re.findall(r"json(.+?)", md, flags=re.S)
print(res[0].strip()) # 完整取出JSON多行内容

替代方案(无需标志位):`[\s\S]` 等价所有字符 ```python res = re.findall(r"```json([\s\S]+?)```", md)

6.2 re.M / re.MULTILINE 多行锚点模式

仅修改^$,让其匹配每一行开头/结尾,不改变.匹配规则,无法解决跨行提取。

text="第一行\n第二行\n第三行"# 匹配所有以“第”开头的行res=re.findall(r"^第.*",text,re.M)print(res)# ['第一行', '第二行', '第三行']

6.3 re.I / re.IGNORECASE 忽略大小写匹配

text="Apple APPLE apple"res=re.findall(r"apple",text,re.I)print(res)# ['Apple', 'APPLE', 'apple']

七、贪婪匹配与非贪婪匹配(开发高频坑)

7.1 贪婪(默认)

*+{m,n}默认尽可能匹配最长文本,容易匹配范围过大。

text="<div>内容1</div><div>内容2</div>"# 贪婪,一次性匹配到最后一个</div>res=re.findall(r"<div>(.+)</div>",text)print(res)# ['内容1</div><div>内容2']

7.2 非贪婪(加?)

量词后增加?,匹配最短符合内容,多标签/多代码块场景必备。

res=re.findall(r"<div>(.+?)</div>",text)print(res)# ['内容1', '内容2']

八、实战业务案例(可直接复用)

案例1:校验手机号完整格式

defcheck_phone(phone):pattern=r"^1[3-9]\d{9}$"ifre.match(pattern,phone):returnTruereturnFalseprint(check_phone("13812345678"))# Trueprint(check_phone("12345678900"))# False

案例2:提取Markdown所有代码块

md_text="""# 测试文档```pythondefhello():print("hello")
{"key":"value"}

“”"

提取代码语言+代码内容

blocks = re.findall(r"(\w+)\n([\s\S]+?)“, md_text)
for lang, code in blocks:
print(f"语言:{lang}\n代码:\n{code.strip()}\n—”)

### 案例3:清洗日志,提取所有数字 ```python log = "2026-07-07 接口耗时 128ms,请求ID 987654,错误码 0" nums = re.findall(r"\d+", log) print(nums) # ['2026','07','07','128','987654','0']

案例4:批量隐藏身份证中间数字

text="张三身份证500101199901011234,李四510202200002024567"new_text=re.sub(r"(\d{6})\d{8}(\d{4})",r"\1********\2",text)print(new_text)# 张三身份证500101********1234,李四510202********4567

九、常见踩坑总结

  1. 跨行文本匹配返回空列表
    原因:.默认不匹配换行;解决方案:加re.S或替换[\s\S]+?
  2. 正则包含\被转义失效
    解决方案:全部使用原始字符串r"表达式"
  3. 多个标签/代码块一次性匹配到底
    原因:贪婪匹配;解决方案:量词后加?改为非贪婪。
  4. match只能匹配开头,误以为全局搜索
    区分:match从头匹配,search全局找第一个,findall提取全部。
  5. 混淆re.M和re.S
    re.M只改变行首尾锚点,不能解决.无法跨换行问题。
  6. 匹配结果为空列表直接取res[0]报错
    规范写法:先判断if res:再取值,增加容错。

十、总结

  1. Python通过内置re模块实现正则,原始字符串r""是规范写法;
  2. 六大核心函数:match/search/findall/sub/split/compile,按业务场景选用;
  3. 跨行文本提取必用re.S标志位,解决.不识别换行的核心痛点;
  4. 多段混杂文本必须使用非贪婪+?,避免匹配范围溢出;
  5. 分组()配合group()可精准提取结构化片段,适合日志、代码块、证件解析;
  6. 正则是文本处理利器,爬虫、数据清洗、接口文本过滤、格式校验场景均不可替代。
http://www.cnnetsun.cn/news/3213533.html

相关文章:

  • AI 辅助 Code Review 的团队落地:从试用到痛点解决的完整路径
  • ChatGPT已过时?揭秘AI Agent如何彻底改变你的工作方式!
  • Acrobat Pro DC 2024安装本质:云原生软件的三方握手认证
  • 这次终于选对了!2026年亲测好用的专业AI论文写作软件
  • 音频处理深入:混音、降噪、音量调节与格式转换
  • ADP5350电源管理IC在嵌入式系统中的应用与优化
  • 绵竹深夜连震,iPhone 用户只能刷朋友圈?我写了一个开源地震预警系统
  • 采购智慧养老设备总踩坑?星梦云康轻量化方案提供参考
  • A股实时行情 API 接入教程:TickDB REST ticker、K线与 WebSocket 实测
  • 2026OpenClaw企业版品牌下载推荐 八款商用智能体分行业量化选型测评指南
  • PyTorch 2.0 线性回归实战:3步从数据加载到模型保存(附完整代码)
  • ZIP密码破解工具对比:ARCHPR vs fcrackzip vs ZipCracker 3款实战评测
  • TraceID 跨越异步任务:不要让消息队列切断调用链
  • 孩子书桌用什么灯好?盘点护眼效果好的护眼台灯,品质过硬!
  • 半导体超纯水系统 2026:3种主流配置方案与18.2 MΩ·cm水质保障
  • 2026工程物资管理软件哪个好?5款轻付费和免费的管理软件对比!
  • 智算中心冷板批量焊接的产能瓶颈:柔性换型怎么破?
  • 多版本Python共存以及环境变量配置
  • 翠湖逛累了别瞎跑!翠怡酒店旁藏着机关食堂开的便民小吃点
  • 报社登报多少钱?报社登报如何办理?办理须注意什么?
  • 全终端接入:OKCC呼叫中心五大接入方式的技术实现解析
  • 深化实验室数智化管理:广凌实验室一体化管理系统的创新实践
  • 太原装修最容易后悔的10个设计|花钱添堵!入住90%想拆掉
  • 银行流水识别工具怎么选?企业批量处理要看字段、结构和复核路径
  • MEMS倾角振动一体机 vs 独立传感器:工业监测系统集成度与边缘计算能力对比分析
  • Outlook、GMX、华为花瓣邮箱3款安全邮箱深度解析:隐私保护与反垃圾实战配置
  • 翻译够准 沟通够稳
  • 德国宣誓翻译件怎么弄?很简单!只需要这三步!
  • 2026儿童口腔健康:专业运营学习伙伴助您一臂之力
  • 力扣560. 和为 K 的子数组中,哈希表mp为什么要mp[0] = 1 ?