Python 正则表达式实战
正则表达式是文本处理的瑞士军刀:提取邮箱、校验手机号、清洗日志。本文从 re 模块核心函数到常用模式,讲清 Python 正则表达式怎么用。
一、re 模块核心函数
import re
# re.match:从字符串开头匹配
result = re.match(r"hello", "hello world")
print(result.group()) # hello
# re.search:搜索整个字符串,找第一个匹配
result = re.search(r"world", "hello world")
print(result.group()) # world
# re.findall:找所有匹配,返回列表
results = re.findall(r"\d+", "订单 100 件,单价 25 元")
print(results) # ['100', '25']
# re.sub:替换
text = re.sub(r"\s+", " ", "a b c")
print(text) # a b c
# re.split:分割
parts = re.split(r"[,;]", "a,b;c,d")
print(parts) # ['a', 'b', 'c', 'd']
二、常用元字符
| 符号 | 含义 | 例子 |
|---|---|---|
| . | 任意字符(除换行) | a.c 匹配 abc、a1c |
| \d | 数字 | \d+ 匹配 123 |
| \w | 字母数字下划线 | \w+ 匹配 hello_1 |
| \s | 空白字符 | \s+ 匹配多个空格 |
| * | 0 次或多次 | ab* 匹配 a、ab、abb |
| + | 1 次或多次 | ab+ 匹配 ab、abb |
| ? | 0 次或 1 次 | ab? 匹配 a、ab |
| {n,m} | n 到 m 次 | \d{11} 匹配 11 位手机号 |
三、分组与捕获
# 提取邮箱用户名和域名
result = re.search(r"(\w+)@(\w+\.\w+)", "user@example.com")
print(result.group(1)) # user
print(result.group(2)) # example.com
# 命名分组
result = re.search(r"(?P\w+)@(?P\w+\.\w+)", "user@example.com")
print(result.group("username")) # user
print(result.group("domain")) # example.com
# 替换中引用分组
text = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", "2026-10-23")
print(text) # 23/10/2026
原始字符串:正则表达式推荐用 r 前缀的原始字符串写法,避免反斜杠转义混乱。例如
r"\d+" 比 "\\d+" 清晰。
四、常用正则实战
# 提取手机号
text = "联系电话:13812345678"
phone = re.search(r"1[3-9]\d{9}", text)
print(phone.group()) # 13812345678
# 提取 URL
html = '链接'
url = re.search(r'href="(https?://[^"]+)"', html)
print(url.group(1)) # https://example.com
# 校验邮箱
email = "test@example.com"
is_valid = re.match(r"^[\w.+-]+@[\w-]+\.[\w.]+$", email)
print(bool(is_valid)) # True
# 提取 HTML 标签内容
html = "标题
内容
"
titles = re.findall(r"(.*?)
", html)
print(titles) # ['标题']
五、预编译正则
# 多次使用同一个正则时,预编译提升性能
phone_pattern = re.compile(r"1[3-9]\d{9}")
# 复用
texts = ["电话13812345678", "电话13987654321", "无号码"]
for text in texts:
m = phone_pattern.search(text)
if m:
print(m.group())
六、贪婪与非贪婪
# 贪婪匹配:尽可能多匹配
re.findall(r"<.+>", "") # ['']
# 非贪婪匹配(加 ?):尽可能少匹配
re.findall(r"<.+?>", "") # ['', '']
# 实战:提取标签内容用非贪婪
html = "第一段
第二段
"
re.findall(r"(.*?)
", html) # ['第一段', '第二段']
七、总结
正则表达式的核心是 re 模块的五个函数:match、search、findall、sub、split。记住常用元字符(\d \w \s + * ?),用分组捕获需要的内容,用非贪婪(?)避免过度匹配。多次使用时预编译提升性能。正则不是万能的,复杂 HTML 解析还是用 BeautifulSoup。