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

Python 正则表达式完全指南:从基础语法到实战案例

正则表达式(Regular Expression)是处理字符串匹配、提取、替换的强大工具,在数据清洗、表单验证、文本分析等场景中应用广泛。本文基于 Python 的 re 模块,结合基础语法与实战案例,带你系统掌握正则表达式的使用方法。


一、正则表达式基础语法

正则表达式的核心是 “匹配模式”,通过特定符号组合定义规则,匹配符合条件的字符串。以下是常用语法分类总结:

1. 精确匹配与选择匹配

  • 精确匹配:直接写目标字符串,匹配完全一致的内容。
    示例:red 仅匹配字符串 "red"。
  • 选择匹配:用 | 分隔多个选项,匹配任意一个选项。
    示例:red|yellow|blue 匹配 "red"、"yellow" 或 "blue"。

2. 模糊匹配(字符集与元字符)

当需要匹配 “某一类字符” 时,使用字符集或元字符(元字符是字符集的简化写法)。

(1)字符集 [ ]
  • [abc]:匹配 "a"、"b"、"c" 中的任意一个字符。
  • [^abc]:匹配除 "a"、"b"、"c" 以外的任意字符(^ 表示 “非”)。
  • [0-9]:匹配 0-9 中的任意一个数字。
  • [a-z]/[A-Z]:匹配小写 / 大写英文字母。
  • [A-z]:匹配英文字母(含大小写)或下划线 _(注意:ASCII 表中 Z 与 a 之间有特殊字符,实际推荐用 [a-zA-Z_])。
  • [\u4e00-\u9fa5]:匹配任意一个中文汉字(Python 支持 Unicode 编码)。
(2)元字符

元字符是字符集的 “简写形式”,更简洁高效:

元字符含义等价字符集
\d匹配数字[0-9]
\D匹配非数字[^0-9]
\w匹配字母、数字、下划线[a-zA-Z0-9_]
\W匹配非字母、数字、下划线[^a-zA-Z0-9_]
.匹配除换行符 \n 外的任意字符-
`\d\D`匹配任意字符(包括换行符)-

3. 量词:控制匹配次数

量词用于定义 “前面的字符 / 表达式需要匹配多少次”,解决 “重复匹配” 问题:

量词含义示例
re{n}匹配 re 恰好 n 次\d{3} 匹配 3 位数字(如 "123")
re{n,}匹配 re 至少 n 次\d{2,} 匹配 2 位及以上数字(如 "12"、"123")
re{n,m}匹配 re 至少 n 次、最多 m 次\d{2,4} 匹配 2-4 位数字(如 "12"、"1234")
re?匹配 re 0 次或 1 次(可选)ab? 匹配 "a" 或 "ab"
re+匹配 re 1 次或多次\d+ 匹配 1 位及以上数字
re*匹配 re 0 次或多次a* 匹配 ""、"a"、"aa" 等
贪婪匹配与非贪婪匹配
  • 贪婪匹配:默认行为,尽可能多匹配(“能多不少”)。
    示例:\d{2,4} 匹配 "12345" 时,会优先匹配 4 位数字 "1234"。
  • 非贪婪匹配:在量词后加 ?,尽可能少匹配(“能少不多”)。
    示例:\d{2,4}? 匹配 "12345" 时,会优先匹配 2 位数字 "12"。

4. 限定符:锚定匹配位置

限定符用于定义 “匹配的字符串必须在什么位置”,常见的有:

  • ^:匹配字符串的开头
    示例:^abc 仅匹配以 "abc" 开头的字符串(如 "abc123",不匹配 "123abc")。
  • $:匹配字符串的结尾
    示例:abc$ 仅匹配以 "abc" 结尾的字符串(如 "123abc",不匹配 "abc123")。
  • ^abc$:精确匹配整个字符串(只能是 "abc",长度和内容完全一致)。

5. 分组:提取与复用匹配结果

用 () 对正则表达式分组,可实现 “提取子结果” 和 “复用匹配规则”。

(1)普通分组

每个 () 对应一个分组,分组索引从 1 开始(0 是整个匹配结果)。
示例:(\d{2})([a-z]+) 匹配 "12ab" 时,分组 1 是 "12",分组 2 是 "ab"。

(2)命名捕获分组

用 (?P<name>re) 给分组命名,后续可通过名称获取结果(更易读)。
示例:(?P<year>\d{4})-(?P<month>\d{2}) 匹配 "2024-05" 时,可通过 "year" 获取 "2024","month" 获取 "05"。

(3)非捕获分组

用 (?:re) 取消分组的 “捕获功能”(仅用于分组匹配,不单独提取结果)。
示例:(?:abc)|(?:def) 匹配 "abc" 或 "def",但不单独捕获分组结果。

(4)反向引用

用 \n(n 是分组索引)复用前面分组的匹配结果,常用于匹配 “重复模式”。
示例:

  • (.)(.)\1\2 匹配 "ABAB" 类型(如 "abab"、"1212")。
  • (.)\1(.)\2 匹配 "AABB" 类型(如 "aabb"、"1122")。

6. 断言:有条件的匹配

断言是 “附加条件的匹配”,不消耗字符,仅判断条件是否满足(也叫 “零宽断言”)。

断言类型语法含义示例
正向确定断言re(?=rex)匹配后面是 rex 的 re\d+(?=px) 匹配 "12px" 中的 "12"
正向否定断言re(?!rex)匹配后面不是 rex 的 re\d+(?!px) 匹配 "12cm" 中的 "12"
反向确定断言(?<=rex)re匹配前面是 rex 的 re(?<=¥)\d+ 匹配 "¥100" 中的 "100"
反向否定断言(?<!rex)re匹配前面不是 rex 的 re(?<!¥)\d+ 匹配 "$100" 中的 "100"

7. 经典案例:密码强度验证

需求:密码必须包含数字、大小写字母、特殊符号(!@#$%^&*),长度 8-18 位。
正则表达式:^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*]).{8,18}$
解析:

  • (?=.*[0-9]):确保包含至少一个数字。
  • (?=.*[a-z]):确保包含至少一个小写字母。
  • (?=.*[A-Z]):确保包含至少一个大写字母。
  • (?=.*[!@#$%^&*]):确保包含至少一个特殊符号。
  • .{8,18}:匹配 8-18 位任意字符(除换行符)。
  • ^ 和 $:锚定整个字符串,避免前后有多余字符。

二、Python re 模块核心方法

Python 的 re 模块提供了正则表达式的核心操作,以下是常用方法的详解与示例。

1. match(pattern, string, flags=0)

  • 功能:从字符串开头匹配,若开头不匹配则返回 None,匹配成功返回 Match 对象。
  • 参数
    • pattern:正则表达式(字符串或编译后的对象)。
    • string:待匹配的字符串。
    • flags:匹配模式(如 re.I 忽略大小写,re.S 让 . 匹配换行符)。

示例

import re# 命名捕获分组示例
res = re.match(r'(?P<first>\d{2})(?P<second>\d{2})', '1234ab')
print(res.span())       # 返回匹配区间 (0, 4)(匹配了前4个字符 "1234")
print(res.groups())     # 返回所有分组元组 ('12', '34')
print(res.group())      # 返回整个匹配结果 '1234'
print(res.group(1))     # 返回第1个分组结果 '12'
print(res.groupdict())  # 返回命名分组字典 {'first': '12', 'second': '34'}

2. fullmatch(pattern, string, flags=0)

  • 功能:匹配整个字符串(从开头到结尾),完全符合正则才返回 Match 对象,否则返回 None
  • 场景:用于严格验证(如手机号、身份证号)。

示例

import re# 验证手机号(11位数字)
res = re.fullmatch(r'\d{11}', '12345678903abc')
print(res)  # None(字符串末尾有 "abc",不满足11位数字)res = re.fullmatch(r'\d{11}', '12345678903')
print(res)  # <re.Match object; span=(0, 11), match='12345678903'>(匹配成功)

3. findall(pattern, string, flags=0)

  • 功能:查找字符串中所有符合正则的子串,返回列表(无匹配则返回空列表)。
  • 分组影响
    • 无分组:返回所有匹配结果的列表。
    • 1 个分组:返回仅包含分组结果的列表。
    • 多个分组:返回列表,每个元素是分组结果的元组。

示例

import re# 多个分组:提取数字+字母组合
res = re.findall(r'(\d+)([a-z]+)', 'ab12cd34ef')
print(res)  # [('12', 'cd'), ('34', 'ef')](每个元组是一组数字+字母)# 无分组:提取所有数字
res = re.findall(r'\d+', 'ab12cd34ef')
print(res)  # ['12', '34']

4. search(pattern, string, flags=0)

  • 功能:在字符串中任意位置查找第一个符合正则的子串,返回 Match 对象(无匹配则返回 None)。
  • 区别于 matchmatch 仅从开头匹配,search 可匹配任意位置。

示例

import re# 查找第一个数字+字母组合
res = re.search(r'(\d+)([a-z]+)', 'ab12cd34ef')
print(res.group())    # '12cd'(整个匹配结果)
print(res.groups())   # ('12', 'cd')(分组结果)

5. sub(pattern, repl, string, count=0, flags=0)

  • 功能:替换字符串中符合正则的子串,返回替换后的新字符串。
  • 参数
    • repl:替换后的内容(字符串或函数)。
    • count:替换次数(0 表示替换所有,默认 0)。
  • 分组引用:在 repl 中用 \n(n 是分组索引)引用分组结果。

示例

import re# 替换所有数字+字母组合为 "中"
res = re.sub(r'\d+[a-z]+', '中', '12cd34ab')
print(res)  # '中中'# 手机号脱敏:13623456789 → 136****6789
res = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', '13623456789')
print(res)  # '136****6789'(\1 引用前3位,\2 引用后4位)# 限制替换次数(仅替换1次)
res = re.sub(r'\d+', '中', '12cd34ab', count=1)
print(res)  # '中cd34ab'

6. subn(pattern, repl, string, count=0, flags=0)

  • 功能:与 sub 类似,但返回元组 (替换后的字符串, 替换次数)

示例

import reres = re.subn(r'\d+', '中', '12cd34ab')
print(res)  # ('中cd中ab', 2)(替换后的字符串 + 替换了2次)

三、实战:任务清单表单验证

结合正则表达式与 re 模块,实现任务清单中的表单验证功能(如手机号、邮箱、任务名长度):

import redef validate_phone(phone):"""验证手机号(11位数字)"""pattern = r'^\d{11}$'return bool(re.fullmatch(pattern, phone))def validate_email(email):"""验证邮箱(如 xxx@xxx.com)"""pattern = r'^\w+@\w+(\.[a-zA-Z]{2,3}){1,2}$'return bool(re.fullmatch(pattern, email))def validate_task_name(name):"""验证任务名(1-50位字符,不包含特殊符号)"""pattern = r'^[a-zA-Z0-9\u4e00-\u9fa5]{1,50}$'return bool(re.fullmatch(pattern, name))# 测试
print(validate_phone('13623456789'))  # True
print(validate_email('test@163.com')) # True
print(validate_task_name('学习正则表达式!')) # False(包含特殊符号 "!")

四、常见问题与注意事项

  1. 转义字符问题:Python 字符串中的 \ 需要转义(如 \d 需写为 r'\d' 或 '\\d'),推荐用 原始字符串 r'' 避免转义麻烦。
  2. 匹配模式 flags
    • re.I:忽略大小写(如 re.match(r'abc', 'ABC', re.I) 匹配成功)。
    • re.S:让 . 匹配换行符(默认不匹配)。
    • re.M:多行模式(让 ^/$ 匹配每行的开头 / 结尾)。
  3. 性能优化:频繁使用的正则表达式,用 re.compile(pattern) 编译为对象,可提高执行效率。
http://www.xdnf.cn/news/1378657.html

相关文章:

  • 【从0带做】基于Springboot3+Vue3的呱呱同城(微服务项目)
  • 实现微信小程序的UniApp相机组件:拍照、录像与双指缩放
  • ARM相关的基础概念和寄存器
  • PCIe 5.0 SSD连续读写缓存用完速度会骤降吗?
  • 2024年09月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • 帕累托优化:多目标决策的智慧与艺术
  • 【重学 MySQL】九十二、 MySQL8 密码强度评估与配置指南
  • 关于virtual camera
  • 【C++游记】模板升级
  • 【半导体制造流程概述】
  • windows 子系统 wsl 命令的用法
  • vue3 字符 居中显示
  • SpringBoot整合Redis:从入门到实战的完整指南
  • 关于DTO、DO、BO、VO
  • 工业 DCS 全面科普:从入门到 AI 赋能的未来
  • mybatis-plus实现苍穹外卖项目-分类操作,不定期更新-day2
  • 【和春笋一起学C++】(三十七)类的析构函数
  • 死锁产生的条件是什么? 如何进行死锁诊断?
  • leetcode 974 和可被K整除的子数组
  • 集成电路学习:什么是YOLO一次性检测器
  • 关于国产 RAC 和分布式研讨
  • 【Python学习笔记】whl包打包
  • Day14——JavaScript 核心知识全解析:变量、类型与操作符深度探秘
  • Redis实战-优惠券秒杀解决方案总结大全
  • XC6SLX75-2FGG484C Xilinx Spartan-6 LX FPGA
  • 电子电气架构 --- 软件项目复杂性的驾驭思路
  • 基于Prometheus Pushgateway与Alertmanager的自定义指标监控与告警实践指南
  • C语言 | 高级C语言面试题
  • C语言二级考试环境配置教程【window篇】
  • 数学建模——马尔科夫链(Markov Chain Model)