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

【Python-Day 42】解锁文本处理神技:Python 正则表达式 (Regex) 从入门到实战

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

Python系列文章目录

01-【Python-Day 1】告别编程恐惧:轻松掌握 Python 安装与第一个程序的 6 个步骤
02-【Python-Day 2】掌握Python基石:变量、内存、标识符及int/float/bool数据类型
03-【Python-Day 3】玩转文本:字符串(String)基础操作详解 (上)
04-【Python-Day 4】玩转文本:Python 字符串常用方法深度解析 (下篇)
05-【Python-Day 5】Python 格式化输出实战:%、format()、f-string 对比与最佳实践
06- 【Python-Day 6】从零精通 Python 运算符(上):算术、赋值与比较运算全解析
07-【Python-Day 7】从零精通 Python 运算符(下):逻辑、成员、身份运算与优先级规则全解析
08-【Python-Day 8】从入门到精通:Python 条件判断 if-elif-else 语句全解析
09-【Python-Day 9】掌握循环利器:for 循环遍历序列与可迭代对象详解
10-【Python-Day 10】Python 循环控制流:while 循环详解与 for 循环对比
11-【Python-Day 11】列表入门:Python 中最灵活的数据容器 (创建、索引、切片)
12-【Python-Day 12】Python列表进阶:玩转添加、删除、排序与列表推导式
13-【Python-Day 13】Python 元组 (Tuple) 详解:从创建、操作到高级应用场景一网打尽
14-【Python-Day 14】玩转Python字典(上篇):从零开始学习创建、访问与操作
15-【Python-Day 15】深入探索 Python 字典 (下):常用方法、遍历、推导式与嵌套实战
16-【Python-Day 16】代码复用基石:详解 Python 函数的定义与调用
17-【Python-Day 17】玩转函数参数(上):轻松掌握位置、关键字和默认值
18-【Python-Day 18】玩转函数参数(下):*args 与 **kwargs 终极指南
19-【Python-Day 19】函数的回响:深入理解 return 语句与返回值
20-【Python-Day 20】揭秘Python变量作用域:LEGB规则与global/nonlocal关键字详解
21-【Python-Day 21】一行搞定!Python lambda 匿名函数的妙用与实战
22-【Python-Day 22】代码的基石:模块(Module)的导入与使用详解
23-【Python-Day 23】Python 模块化编程实战:创建、导入及 sys.path 深度解析
24-【Python-Day 24】告别杂乱代码!一文掌握 Python 包(Package)的创建与使用
25-【Python-Day 25】玩转数字:精通 math 与 random 模块,从数学运算到随机抽样
26-【Python-Day 26】解锁时间魔法:深入解析 time 与 datetime 模块
27-【Python-Day 27】轻松驾驭操作系统:精通 os 与 sys 模块核心功能
28-【Python-Day 28】从指令到蓝图:Python面向对象编程(OOP)入门指南
29-【Python-Day 29】万物皆对象:详解 Python 类的定义、实例化与 __init__ 方法
30-【Python-Day 30】从 self、cls 到 @staticmethod:Python 面向对象三大方法深度解析
31-【Python-Day 31】一文搞懂 Python 实例属性与类属性:从定义、区别到应用场景
32-【Python-Day 32】面向对象基石之封装:从 __private@property 的深度解析
33-【Python-Day 33】OOP核心之继承(Inheritance):代码复用与扩展的艺术
34-【Python-Day 34】深入解析Python继承:super()函数、MRO与菱形继承问题
35-【Python-Day 35】深入理解多态:代码更灵活的“鸭子类型”魔法
36-【Python-Day 36】解密文件IO:一文搞懂 Python 读写模式、编码与指针操作
37-【Python-Day 37】程序的守护者:一文彻底搞懂 Python 异常处理 (try-except-else-finally)
38-【Python-Day 38】告别通用错误!一文学会创建和使用 Python 自定义异常
39-【Python-Day 39】精通Python推导式:告别冗长for循环,提升代码效率与格调
40-【Python-Day 40】告别内存溢出!Python 生成器 (Generator) 的原理与实战
41-【Python-Day 41】揭秘函数的“魔法外衣”:一文彻底搞懂 Python 装饰器 (Decorator)
42-【Python-Day 42】解锁文本处理神技:Python 正则表达式 (Regex) 从入门到实战


文章目录

  • Langchain系列文章目录
  • Python系列文章目录
  • PyTorch系列文章目录
  • 机器学习系列文章目录
  • 深度学习系列文章目录
  • Java系列文章目录
  • JavaScript系列文章目录
  • Python系列文章目录
  • 摘要
  • 一、初识正则表达式:文本世界的“精准制导”
    • 1.1 什么是正则表达式?
    • 1.2 为什么需要学习正则表达式?
  • 二、正则表达式的核心:元字符的奥秘
    • 2.1 基础元字符:定位与匹配
    • 2.2 量词元字符:控制重复次数
      • 2.2.1 贪婪模式 vs. 非贪婪模式
    • 2.3 字符集与其他特殊字符
    • 2.4 预定义字符集
  • 三、Python 的 `re` 模块实战
      • 3.0.1 原始字符串 (Raw String)
    • 3.1 核心函数概览
    • 3.2 `re.match()`:从头开始匹配
      • 3.2.1 语法与示例
    • 3.3 `re.search()`:全局搜索第一个匹配
      • 3.3.1 语法与示例
    • 3.4 `re.findall()`:查找所有匹配
      • 3.4.1 语法与示例
    • 3.5 `re.sub()`:搜索与替换
      • 3.5.1 语法与示例
  • 四、进阶技巧与最佳实践
    • 4.1 编译正则表达式:`re.compile()`
      • 4.1.1 使用方法
    • 4.2 分组与捕获:强大的 `()`
      • 4.2.1 提取邮件的用户名和域名
  • 五、总结


摘要

在处理字符串时,我们经常会遇到比简单查找和替换更复杂的需求,例如,验证一个字符串是否是合法的电子邮件地址、从一段文本中提取所有电话号码,或者将文本中所有符合特定模式的子串替换掉。对于这些任务,Python 内置的字符串方法可能显得力不从心。这时,强大的**正则表达式(Regular Expression, Regex)**就派上了用场。本文将带你从零开始,系统学习 Python 中的 re 模块,掌握正则表达式这一文本处理的终极利器,让你能够高效、精准地驾驭任何复杂的字符串操作。

一、初识正则表达式:文本世界的“精准制导”

在学习具体语法之前,我们先来理解正则表达式到底是什么。

1.1 什么是正则表达式?

想象一下,你想在成千上万份文档中找到所有的联系人电话。这些电话号码格式各异,有的是 138-1234-5678,有的是 (010)12345678,还有的是 139 1111 2222。如果用普通的字符串查找,你可能需要写很多个 find(),非常繁琐且容易遗漏。

正则表达式,就是一种用于描述、匹配一系列字符串共同特征的“模式模板”。它使用一套特殊的字符(称为元字符)来定义一个搜索规则,然后用这个规则去文本中进行匹配。对于上面的电话号码问题,我们可以用一个简单的正则表达式 \d{3,4}-?\d{7,8} 来匹配大多数情况。

简单来说,正则表达式为你提供了一套极其强大的“文本检索语法”,让你能用一个简洁的模式描述出你想要查找的内容。

1.2 为什么需要学习正则表达式?

  • 高效精准:一个复杂的文本匹配任务,用正则表达式可能一行代码就能解决,而用传统方法可能需要数十行。
  • 应用广泛:无论是数据清洗、网络爬虫、日志分析、还是后端开发中的数据校验,正则表达式都是不可或缺的工具。
  • 语言通用:正则表达式是一套独立的规范,在 Python、Java、JavaScript、Go 等几乎所有主流编程语言中都有实现,学会它将终身受益。

在 Python 中,我们主要通过内置的 re 模块来使用正则表达式。

二、正则表达式的核心:元字符的奥秘

元字符是构成正则表达式的基石,它们是一些具有特殊含义的字符,用于定义匹配规则。下面我们将它们分类进行学习。

2.1 基础元字符:定位与匹配

元字符名称功能描述示例匹配对象
.匹配除换行符 \n 之外的任意单个字符。p.ppp 之间有任意一个字符的字符串,如 “pyp”, “p_p”, “p9p”。
^脱字符匹配字符串的开头。^Hello以 “Hello” 开头的字符串,如 “Hello World”。
$美元符匹配字符串的结尾。world$以 “world” 结尾的字符串,如 “hello world”。

2.2 量词元字符:控制重复次数

量词用来指定它前面的一个字符或一个分组可以出现的次数。

元字符名称功能描述示例匹配对象
*星号匹配前面的子表达式零次或多次。go*d“gd”, “god”, “good”, “gooood” 等。
+加号匹配前面的子表达式一次或多次。go+d“god”, “good”, “gooood” 等 (不包括 “gd”)。
?问号匹配前面的子表达式零次或一次。colou?r“color” 或 “colour”。
{n}大括号精确匹配前面的子表达式 n 次。\d{3}恰好 3 个数字,如 “123”。
{n,}大括号匹配前面的子表达式至少 n 次。\d{2,}至少 2 个数字,如 “12”, “12345”。
{n,m}大括号匹配前面的子表达式 nm 次。\d{2,4}2 到 4 个数字,如 “12”, “123”, “1234”。

2.2.1 贪婪模式 vs. 非贪婪模式

默认情况下,*, +, {n,} 等量词是贪婪的(Greedy),它们会尽可能多地匹配字符。例如,对于字符串 "<html><h1>Title</h1></html>",正则表达式 <.*> 会匹配整个字符串,而不是只匹配 <html>

要切换到非贪婪模式(Non-Greedy),只需在量词后面加上一个 ?

  • *?: 非贪婪匹配,匹配零次或多次,但尽可能少地匹配。
  • +?: 非贪婪匹配,匹配一次或多次,但尽可能少地匹配。
  • {n,m}?: 非贪婪匹配,匹配 n 到 m 次,但尽可能少地匹配。

示例:

import retext = "<html><h1>Title</h1></html>"# 贪婪模式
greedy_match = re.search(r"<.*>", text)
print(f"贪婪匹配结果: {greedy_match.group(0)}")# 非贪婪模式
non_greedy_match = re.search(r"<.*?>", text)
print(f"非贪婪匹配结果: {non_greedy_match.group(0)}")

输出:

贪婪匹配结果: <html><h1>Title</h1></html>
非贪婪匹配结果: <html>

2.3 字符集与其他特殊字符

元字符名称功能描述示例匹配对象
[]字符集匹配方括号中的任意一个字符。[abc]“a”, “b”, “c” 中的任意一个。
[^]否定字符集匹配任何不在方括号中的字符。[^abc]除了 “a”, “b”, “c” 之外的任意一个字符。
[a-z]范围匹配指定范围内的任意一个字符。[0-9], [A-Z]任意一个数字,任意一个大写字母。
``匹配 `` 左边或右边的表达式。
()分组将括号内的表达式作为一个整体,并可以捕获这部分匹配的内容。(ab)+一个或多个 “ab”,如 “ab”, “abab”。
\转义符将下一个字符标记为特殊字符或字面值。\.匹配真实的 . 字符,而不是任意字符。

2.4 预定义字符集

为了方便,正则表达式提供了一些预定义的字符集。

字符集等价于描述
\d[0-9]匹配一个数字字符。
\D[^0-9]匹配一个非数字字符。
\w[a-zA-Z0-9_]匹配包括下划线的任何单词字符。
\W[^a-zA-Z0-9_]匹配任何非单词字符。
\s[ \t\n\r\f\v]匹配任何空白字符,包括空格、制表符、换行符等。
\S[^ \t\n\r\f\v]匹配任何非空白字符。

三、Python 的 re 模块实战

掌握了元字符后,我们来看看如何在 Python 中使用 re 模块进行实际操作。

3.0.1 原始字符串 (Raw String)

在 Python 中定义正则表达式时,强烈建议在模式字符串前加上 r 前缀,这表示它是一个“原始字符串”。原始字符串会忽略反斜杠 \ 的转义作用,避免与 Python 的字符串转义规则冲突。

例如,要匹配一个 \ 字符,正则表达式是 \\。如果不用原始字符串,你需要写成 '\\\\' (前两个 \ 转义成一个 \,后两个也一样),而使用原始字符串,只需写成 r'\\',更加直观。

3.1 核心函数概览

re 模块提供了几个核心函数来执行匹配操作:

  • re.match(): 从字符串的起始位置开始匹配。
  • re.search(): 扫描整个字符串,找到第一个匹配项。
  • re.findall(): 找到所有匹配项,并以列表形式返回。
  • re.sub(): 查找并替换。

3.2 re.match():从头开始匹配

此函数尝试从字符串的起始位置匹配一个模式。如果不是起始位置匹配,match() 就返回 None

3.2.1 语法与示例

re.match(pattern, string, flags=0)
  • pattern: 正则表达式模式。
  • string: 要匹配的字符串。
  • flags: 标志位,用于控制匹配方式(如忽略大小写)。
import retext1 = "hello world"
text2 = "python hello"pattern = r"hello"# 在 text1 中,'hello' 在开头,匹配成功
match1 = re.match(pattern, text1) 
if match1:print(f"在 '{text1}' 中找到匹配: {match1.group(0)}") # .group(0) 获取整个匹配的字符串# 在 text2 中,'hello' 不在开头,匹配失败
match2 = re.match(pattern, text2)
if match2:print(f"在 '{text2}' 中找到匹配: {match2.group(0)}")
else:print(f"在 '{text2}' 中,模式 '{pattern}' 不在开头,match() 找不到匹配。")

输出:

在 'hello world' 中找到匹配: hello
在 'python hello' 中,模式 'hello' 不在开头,match() 找不到匹配。

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

search() 会扫描整个字符串,找到并返回第一个成功的匹配。如果找不到匹配,则返回 None

3.3.1 语法与示例

re.search(pattern, string, flags=0)
import retext1 = "hello world"
text2 = "python hello"pattern = r"hello"# 在 text1 中,找到第一个 'hello'
search1 = re.search(pattern, text1)
if search1:print(f"在 '{text1}' 中找到匹配: {search1.group(0)}")# 在 text2 中,即使 'hello' 不在开头,也能找到
search2 = re.search(pattern, text2)
if search2:print(f"在 '{text2}' 中找到匹配: {search2.group(0)}")

输出:

在 'hello world' 中找到匹配: hello
在 'python hello' 中找到匹配: hello

小结match() 像是做“是不是以…开头”的判断,而 search() 则是做“包不包含…”的判断。

3.4 re.findall():查找所有匹配

当你想获取所有满足模式的子串,而不是仅仅第一个时,findall() 是最佳选择。它会返回一个包含所有匹配项的列表

3.4.1 语法与示例

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

应用场景:从文本中提取所有电话号码

import retext = "我的电话是 13812345678, 备用号码是 18987654321。请勿联系 110。"
# \d{11} 表示匹配 11 个连续的数字
phone_numbers = re.findall(r"\d{11}", text)print(f"提取到的所有电话号码: {phone_numbers}")

输出:

提取到的所有电话号码: ['13812345678', '18987654321']

3.5 re.sub():搜索与替换

sub() 用于查找所有匹配的子串,并用一个指定的字符串替换它们。

3.5.1 语法与示例

re.sub(pattern, repl, string, count=0, flags=0)
  • repl: 替换成的字符串。
  • count: 最大替换次数,默认为0,表示全部替换。

应用场景:数据脱敏,隐藏手机号中间四位

import rephone = "13812345678"
# 模式解析:
# (\d{3}) - 第一个分组,匹配前3个数字
# \d{4}   - 匹配中间4个数字 (不捕获)
# (\d{4}) - 第二个分组,匹配后4个数字
# 替换字符串 r'\1****\2' 中:
# \1 表示第一个分组捕获的内容 ('138')
# \2 表示第二个分组捕获的内容 ('5678')
safe_phone = re.sub(r"(\d{3})\d{4}(\d{4})", r"\1****\2", phone)print(f"原始号码: {phone}")
print(f"脱敏后号码: {safe_phone}")

输出:

原始号码: 13812345678
脱敏后号码: 138****5678

四、进阶技巧与最佳实践

4.1 编译正则表达式:re.compile()

如果一个正则表达式需要被重复使用多次,预先将其编译成一个正则表达式对象可以提高效率。因为 re.compile() 会将模式字符串转换成内部格式,后续的匹配操作就不再需要重新解析模式了。

4.1.1 使用方法

import re# 编译模式
email_pattern = re.compile(r'[\w.-]+@[\w.-]+\.\w+')emails = ["test.user@example.com","invalid-email","another_user@sub.domain.co.uk","user@localhost"
]valid_emails = []
for email in emails:# 使用编译好的对象进行匹配if email_pattern.match(email):valid_emails.append(email)print(f"有效的电子邮件地址: {valid_emails}")

输出:

有效的电子邮件地址: ['test.user@example.com', 'another_user@sub.domain.co.uk']

编译后的对象拥有与 re 模块相同的匹配函数(如 match(), search(), findall()),只是不再需要传入 pattern 参数。

4.2 分组与捕获:强大的 ()

括号 () 在正则表达式中有两个主要作用:

  1. 作为一个整体:如 (ab)+ 匹配连续的 ab
  2. 捕获内容:将括号内匹配到的内容保存起来,方便后续引用或提取。

matchsearch 返回的匹配对象(Match Object)提供了 group()groups() 方法来获取捕获的内容。

  • group(0)group(): 返回整个匹配的字符串。
  • group(n): 返回第 n 个分组捕获的内容(从1开始)。
  • groups(): 返回一个包含所有分组捕获内容的元组。

4.2.1 提取邮件的用户名和域名

import reemail = "contact-us@csdnblog.com"
# 模式解析:
# ([\w.-]+) - 第一个分组,捕获用户名部分
# @           - 匹配@符号
# ([\w.-]+) - 第二个分组,捕获域名部分
pattern = re.compile(r"([\w.-]+)@([\w.-]+)")match = pattern.search(email)
if match:print(f"完整匹配 (group 0): {match.group(0)}")print(f"用户名 (group 1): {match.group(1)}")print(f"域名 (group 2): {match.group(2)}")print(f"所有分组 (groups()): {match.groups()}")

输出:

完整匹配 (group 0): contact-us@csdnblog.com
用户名 (group 1): contact-us
域名 (group 2): csdnblog.com
所有分组 (groups()): ('contact-us', 'csdnblog.com')

这种能力在数据提取和解析任务中极为有用。

五、总结

正则表达式是 Python 乃至整个编程世界中处理文本的强大工具。今天,我们系统地学习了它的核心知识,让我们来回顾一下:

  1. 核心思想:正则表达式是一种定义“搜索模式”的语言,用于高效、灵活地匹配和处理字符串。在 Python 中,我们通过 re 模块来使用它。
  2. 元字符是基础 ., ^, $, *, +, ?, [], |, () 等元字符是构建正则表达式的积木,必须熟练掌握它们的含义,特别是量词的贪婪与非贪婪模式。
  3. re 模块四大金刚
    • re.match():只从字符串开头匹配。
    • re.search():在整个字符串中查找第一个匹配。
    • re.findall():查找所有匹配,返回一个列表。
    • re.sub()查找并替换
  4. 最佳实践
    • 使用 r"" 原始字符串来定义模式,避免转义混淆。
    • 对于需要重复使用的模式,使用 re.compile() 进行预编译以提升性能。
    • 善用 () 分组捕获功能,它可以精确提取你需要的特定部分数据。

初学正则表达式可能会觉得其语法有些晦涩,但请不要畏惧。最好的学习方法就是不断练习。尝试为你日常遇到的文本处理问题构建正则表达式,你会很快发现它的强大之处,并将其变为你工具箱中不可或缺的一项神技。


http://www.xdnf.cn/news/1443439.html

相关文章:

  • FPGA离群值剔除算法
  • wpf 自定义输入ip地址的文本框
  • Linux之shell-awk命令详解
  • Jenkins 可观测最佳实践
  • Jenkins和Fastlane的原理、优缺点、用法、如何选择
  • 记录一下node后端写下载https的文件报错,而浏览器却可以下载。
  • nginx配置端口转发(docker-compose方式、包括TCP转发和http转发)
  • C++ 面试高频考点 力扣 162. 寻找峰值 二分查找 题解 每日一题
  • Apache Kafka:现代数据高速公路的设计哲学
  • 嵌入式硬件 - 51单片机2
  • (11)用于无GPS导航的制图师SLAM(二)
  • AI产品经理面试宝典第84天:RAG系统架构设计与优化策略面试指南
  • C#工作流示例(WorkflowCore)
  • 基于Docker和Kubernetes的CI/CD流水线架构设计与优化实践
  • Go语言实战案例-Redis实现用户登录次数限制
  • 基于单片机车内换气温度检测空气质量检测系统Proteus仿真(含全部资料)
  • 02-Media-3-audio.py 音频输入输出,录音、播放、实时回放演示
  • 在 Android MVVM 架构中,获取 ViewModel 的几种方式
  • 微服务的编程测评系统20-虚拟机-nginx-部署
  • 基于Java的瑜伽馆管理系统的设计与实现(代码+数据库+LW)
  • 【LeetCode】21、合并两个有序链表
  • 【设计模式】 装饰模式
  • 【机器学习深度学习】RAG边界处理策略
  • Django REST Framework Serializer 进阶教程
  • word删除指定页面
  • Ubuntu22.04中使用cmake安装abseil-cpp库
  • 【数据分享】283个地级市产业结构合理化水平和产业结构高级化指数(2006-2019)
  • Upload-Labs靶场全20关通关攻略(含原理+实操+环境配置)
  • 利用 Python 绘制环形热力图
  • SuperMap GIS基础产品FAQ集锦(20250819)