Python 正则表达式:权威指南

tags: python, regex, tutorial, programming


Python 正则表达式:权威指南

想象一下,你正面对一个 10,000 行的日志文件,需要在几秒钟内提取出所有的电子邮件地址、IP 地址和时间戳。如果使用手动字符串切片或嵌套循环来完成这项工作,不仅耗时,还很容易在边界情况下出错。但借助 Python 正则表达式,你可以用一行优雅的代码解决这个问题。正则表达式不仅仅是开发者的超级技能,更是模式匹配、文本验证和数据提取的终极工具。让我们一起掌握它。

Python re 模块入门

在编写复杂的正则模式之前,你需要导入正确的工具。Python 通过内置的 re 模块 来处理正则表达式。它轻量、强大,并且在每一个标准 Python 安装中都可用。

import re

Enter fullscreen mode Exit fullscreen mode

开始时的黄金法则:模式字符串始终使用原始字符串。在字符串前加上 r 前缀(例如 r"\d+"),以防止 Python 在正则引擎看到它们之前就将反斜杠解释为转义字符。这样可以避免微妙的错误,例如 \n 变成换行符,而不是字面上的“反斜杠-n”模式。

你每天都会用到的核心正则函数

re 模块提供了几个函数,但以下四个函数是你 90% 时间里会用到的:

re.search()

扫描整个字符串,如果在任何位置找到匹配的模式,则返回一个匹配对象,否则返回 None。它非常适合用于检查某个条件是否存在。

re.match()

仅检查模式是否在字符串的最开头匹配。如果你的文本以额外的空白字符或无关字符开头,即使模式在后面存在,match() 也可能失败。

re.findall()

返回一个所有非重叠匹配项的列表。这是你提取数据的首选方法,例如从文档中提取所有电话号码。

re.sub()

搜索模式的所有实例,并用新字符串替换它们。可用于清理数据或净化输入。

基本模式与特殊字符

正则表达式模式由普通字符(如 a5!)和定义规则的元字符构成。以下是你今天就需要掌握的要点:

元字符 含义
. 任意单个字符(换行符除外)
^ 字符串的开头
$ 字符串的结尾
\d 任意数字(0–9)
\w 任意单词字符(字母、数字或下划线)
\s 任意空白字符(空格、制表符、换行符)

例如,r"\d{3}-\d{4}" 可以匹配像 555-1234 这样的美国电话号码格式。

量词:控制重复

你经常需要匹配字符的“一个或多个”或“零个或多个”。量词用于处理这种情况:

  • *:零个或多个(例如 ab* 匹配 aababb
  • +:一个或多个(例如 ab+ 匹配 ababb,但不匹配 a
  • ?:零个或一个(例如 ab? 匹配 aab
  • {n}:正好 n 次(例如 \d{4} 匹配正好 4 位数字)
  • {n,m}:介于 nm 次之间

锚点与边界

锚点允许你基于位置而非内容进行匹配:

  • ^pattern:仅当模式位于开头时才匹配。
  • pattern$:仅当模式位于结尾时才匹配。
  • \b:单词边界(用于匹配整个单词,如 \bcat\b,以避免匹配“category”)。

一个实用的工作示例

让我们把所有知识整合起来。假设你有一个杂乱的日志字符串,需要提取所有电子邮件地址,将它们替换为 [REDACTED],并统计找到的数量。

import re

log_text = """
User [email protected] logged in from 192.168.1.1.
Error: Invalid email user@@test.com. Contact [email protected].
Another user: [email protected] tried again.
"""

# 1. Define the email pattern
email_pattern = r"[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}"

# 2. Find all emails
emails = re.findall(email_pattern, log_text)
print(f"Found {len(emails)} emails: {emails}")

# 3. Replace them
cleaned_log = re.sub(email_pattern, "[REDACTED]", log_text)
print("\nCleaned Log:")
print(cleaned_log)

Enter fullscreen mode Exit fullscreen mode

输出:

Found 3 emails: ['[email protected]', '[email protected]', '[email protected]']

Cleaned Log:

User [REDACTED] logged in from 192.168.1.1.
Error: Invalid email user@@test.com. Contact [REDACTED].
Another user: [REDACTED] tried again.

Enter fullscreen mode Exit fullscreen mode

请注意,user@@test.com 被忽略了,因为它违反了模式(有两个 @ 符号)。这就是精确正则表达式的强大之处:它会自动过滤噪声

高级技巧:分组与环视

一旦你掌握了基础知识,就可以探索分组 ( ) 来捕获匹配的一部分。例如,r"(\d{4})-(\d{2})-(\d{2})" 可以将日期拆分为年、月、日。

环视(如 (?=...) 正向先行断言)允许你仅在模式后面跟着另一个模式时才匹配,但结果中不包含第二个部分。这些功能对于复杂验证非常强大,但如果过度使用可能会降低性能。

性能提示与最佳实践

正则表达式很快,但如果写得不好,它可能会变慢。以下是如何保持高效的方法:

  • 编译模式以便重复使用:pattern = re.compile(r"\d+"),然后使用 pattern.findall(text)
  • 从简单开始:逐步构建你的模式,并用小输入进行测试。
  • 不要过度使用正则表达式:如果简单的字符串方法(如 .split().replace())能解决问题,就使用它们。正则表达式用于复杂模式,而不是所有字符串任务。
  • 彻底测试:使用 regex101.com 等工具来可视化匹配并调试边界情况。

要点总结

  • 始终使用原始字符串r"pattern")来避免转义问题。
  • 掌握四个核心函数:search()match()findall()sub()
  • 使用量词*+?{n})来控制重复。
  • 使用 ^$ 锚定模式以进行基于位置的匹配。
  • 重复使用时编译模式以提升性能。
  • 部署前用真实数据测试你的模式。

正则表达式是一项通过练习不断成长的技能。今天就从解决一个小问题开始:验证一个电子邮件、提取一个电话号码,或清理 CSV 列。一旦你看到它如何将杂乱的文本转换为结构化数据,你就再也不会回到手动字符串解析了。

准备好升级了吗?找一个杂乱的文本文件,编写一个正则模式来提取你需要的数据,然后在 Dev.to 的评论区分享你的模式。让我们一起建立一个正则表达式巫师社区!


如果你觉得这篇文章有帮助,可以考虑请我喝杯咖啡 ☕ —— 这能让这些文章继续产出!

也可以看看我的 AI 工具合集:AI 次元世界 —— 面向开发者的免费 AI 工具。