在处理海量文本数据时,正则表达式就像是一把手术刀,能够精准地从杂乱无章的字符中切出我们需要的信息。
Python 通过内置的 re 模块,为我们提供了一套极其强大的正则工具箱。
使用原始字符串
正则表达式本质上是一套微型的编程语言,通过特定的符号来描述字符串的规则。在 Python 中,绝大多数普通字符(如字母 'a' 或数字 '1')都代表它们自己。但真正的魔法在于“元字符”,比如 . 可以匹配除换行符以外的任何字符,而 ^ 和 $ 则分别锚定字符串的开头和结尾。
由于正则表达式中经常使用反斜杠 \,为了避免 Python 字符串本身的转义机制产生干扰,强烈建议在编写正则模式时使用 **原始字符串(raw string)**,即在引号前加一个 r。
import re
# 匹配所有的数字,使用 r 前缀避免混淆
pattern = r'\d+'
重复操作符
很多时候,我们并不知道某个模式会出现多少次。这时,重复操作符就派上用场了。* 代表匹配零次或多次,+ 代表一次或多次,而 ? 则表示可选(零次或一次)。如果你想更精确一点,可以使用花括号,比如 {3,5} 意味着匹配 3 到 5 次。
需要注意的是,正则引擎默认是“贪婪”的,它会尽可能多地匹配字符。如果你希望它“见好就收”,可以在重复符号后面加一个问号,开启非贪婪模式。
四种常用方法
拿到正则规则后,如何让它在代码中跑起来?Python 主要提供了四种武器:
- •
match():仅从字符串的开头开始匹配。如果开头不符合规则,直接返回 None。 - •
search():扫描整个字符串,寻找第一个匹配的位置。 - •
findall():找出所有匹配项,并以列表的形式返回。 - •
finditer():最推荐的方法。它返回一个迭代器,能逐个处理匹配到的对象,在大数据量下非常节省内存。
text = "我的电话是 123456,他的电话是 654321"
# 找到所有连续的数字
results = re.findall(r'\d+', text)
print(results) # 输出: ['123456', '654321']
匹配对象分组
当你使用 search() 或 finditer() 成功匹配到内容时,返回的是一个“匹配对象(Match Object)”。这个对象里藏着丰富的宝藏:通过 .group() 可以获取匹配到的文本,.start() 和 .end() 则能告诉你匹配内容在原字符串中的起止位置。
如果你的正则里使用了括号 (),这就创建了“分组”。你可以通过 .group(1)、.group(2) 等方式单独提取出括号里的局部信息。这在提取像邮箱前缀或日期年、月、日时非常高效。
性能优化
如果你的代码需要频繁使用同一个正则表达式,最好先使用 re.compile() 将其编译成一个模式对象。这样 Python 就可以缓存这个模式,提高运行效率。
此外,正则引擎在遇到复杂的嵌套重复时可能会出现性能骤降,甚至导致回溯灾难。编写正则时,应尽量让模式简洁明确,少用模糊的 .*。
# 预编译,提高后续重复调用的效率
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
if date_pattern.search("今天的日期是 2026-02-27"):
print("日期格式匹配成功!")
正则表达式的学习曲线虽然有些陡峭,一旦掌握,它将极大提升你处理文本的能力。无论是数据清洗、日志分析还是网页爬虫,都能让你事半功倍。