正则表达式速查与实战

正则表达式是文本处理的核心工具,几乎所有编程语言都支持。这篇整理常用语法和Python中re模块的实际用法,方便随时查阅。

元字符速查

符号 含义 示例
. 任意字符(除换行) a.c 匹配 abc, a1c
\d 数字 [0-9] \d{3} 匹配 123
\w 字母数字下划线 \w+ 匹配 hello_123
\s 空白字符 a\sb 匹配 a b
\D \W \S 上面三个的取反
^ 行首 ^Hello
$ 行尾 world$
\b 单词边界 \bcat\b 不匹配 catch

量词

符号 含义
* 0次或多次
+ 1次或多次
? 0次或1次
{n} 恰好n次
{n,} 至少n次
{n,m} n到m次

默认是贪婪匹配(尽可能多),加?变成非贪婪:

import re
text = "<b>bold</b> and <i>italic</i>"
re.findall(r"<.*>", text)    # ['<b>bold</b> and <i>italic</i>']  贪婪
re.findall(r"<.*?>", text)   # ['<b>', '</b>', '<i>', '</i>']      非贪婪

分组与捕获

import re

# 基本分组
m = re.match(r"(\d{4})-(\d{2})-(\d{2})", "2021-02-18")
print(m.group(0))  # 2021-02-18 (整体匹配)
print(m.group(1))  # 2021
print(m.group(2))  # 02

# 命名分组
m = re.match(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2021-02-18")
print(m.group("year"))   # 2021

# 非捕获分组(只分组不捕获)
re.findall(r"(?:https?://)?(\w+\.\w+)", "https://example.com http://test.org")
# ['example.com', 'test.org']

零宽断言

不消耗字符,只匹配位置:

# 正向前瞻 (?=...):后面是...
re.findall(r"\w+(?=@)", "user@example.com")  # ['user']

# 负向前瞻 (?!...):后面不是...
re.findall(r"\d+(?!px)", "12px 34em 56")     # ['34', '56']

# 正向后顾 (?<=...):前面是...
re.findall(r"(?<=\$)\d+", "price $100")      # ['100']

# 负向后顾 (?<!...):前面不是...
re.findall(r"(?<!\d)\d{3}(?!\d)", "12 123 1234")  # ['123']

Python re模块

import re

text = "联系电话: 13812345678, 备用: 13987654321"

# findall: 找所有匹配
phones = re.findall(r"1[3-9]\d{9}", text)
# ['13812345678', '13987654321']

# search: 找第一个匹配
m = re.search(r"1[3-9]\d{9}", text)
print(m.group())  # 13812345678

# sub: 替换
masked = re.sub(r"(1\d{2})\d{4}(\d{4})", r"\1****\2", text)
# "联系电话: 138****5678, 备用: 139****4321"

# split: 按模式分割
parts = re.split(r"[,;\s]+", "a, b; c  d")
# ['a', 'b', 'c', 'd']

# compile: 预编译(多次使用时提升性能)
pattern = re.compile(r"\d{4}-\d{2}-\d{2}")
dates = pattern.findall("日期: 2021-02-18, 截止: 2021-03-01")

常用正则模式

# 邮箱
r"[\w.+-]+@[\w-]+\.[\w.]+"

# 手机号
r"1[3-9]\d{9}"

# URL
r"https?://[\w\-._~:/?#\[\]@!$&'()*+,;=%]+"

# IP地址
r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"

# 身份证号
r"\d{17}[\dXx]"

小结

正则不需要全记住,掌握基本元字符、量词、分组就能覆盖80%的场景。遇到复杂的正则,推荐用 regex101.com 在线调试——可视化的匹配过程比自己脑内解析高效多了。