一、正则表达式简介
正则表达式(Regular Expression, regex)是一种用于匹配、查找、替换字符串模式的强大工具。
在 Python 中由标准库 re 提供支持。
import re
二、基础语法结构
| 类型 | 符号 | 含义 | 示例 | | |
|---|
| 字符匹配 | . | 匹配任意除换行外的字符 | a.c → 匹配 abc, axc | | |
| 字符集 | [abc] | 匹配 a 或 b 或 c | [0-9] 匹配任意数字 | | |
| 否定字符集 | [^abc] | 不匹配 a,b,c | [^0-9] 非数字 | | |
| 转义 | \ | 转义或表示特殊序列 | \d, \s, \w | | |
| 组与范围 | ( ) | 捕获分组 | (abc)+ 匹配多次出现的 “abc” | | |
| 或 | ` | ` | 或逻辑 | `cat | dog` 匹配 “cat” 或 “dog” |
三、量词(重复次数)
| 符号 | 含义 | 示例 |
|---|
* | 重复 0 次或多次 | ab*c → ac, abc, abbc |
+ | 重复 1 次或多次 | ab+c → abc, abbc |
? | 重复 0 或 1 次 | ab?c → ac, abc |
{n} | 重复 n 次 | a{3} → aaa |
{n,} | 至少 n 次 | a{2,} → aa, aaa, … |
{n,m} | n 到 m 次之间 | a{2,4} → aa, aaa, aaaa |
贪婪与非贪婪(懒惰)模式
| 类型 | 含义 | 示例 |
|---|
| 贪婪(默认) | 尽可能多地匹配 | a.*b 匹配最远的 b |
| 非贪婪 | 尽可能少地匹配 | a.*?b 匹配最近的 b |
四、预定义字符集(快捷写法)
| 表达式 | 含义 | 等价 |
|---|
\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] |
五、锚点(位置匹配)
| 符号 | 含义 | 示例 |
|---|
^ | 字符串开头 | ^abc 匹配以 abc 开头 |
$ | 字符串结尾 | abc$ 匹配以 abc 结尾 |
\b | 单词边界 | \bcat\b 仅匹配独立单词 “cat” |
\B | 非单词边界 | \Bcat\B |
六、分组与反向引用
捕获分组
m = re.match(r'(\d{4})-(\d{2})-(\d{2})', '2025-10-31')
print(m.group(1))
print(m.group(2))
print(m.group(3))
命名分组
m = re.match(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', '2025-10-31')
print(m.group('year'))
反向引用
re.search(r'(\b\w+)\s+\1', 'hello hello world')
七、前瞻与后顾(零宽断言)
| 类型 | 写法 | 含义 | 示例 |
|---|
| 正向前瞻 | (?=...) | 匹配后面满足条件的字符串 | \d(?=px) 匹配 “12px” 中的 “2” |
| 负向前瞻 | (?!...) | 匹配后面不满足条件的字符串 | \d(?!px) |
| 正向后顾 | (?<=...) | 匹配前面满足条件的字符串 | (?<=\$)\d+ 匹配 “$99” 中的 “99” |
| 负向后顾 | (?<!...) | 匹配前面不满足条件的字符串 | (?<!\$)\d+ |
这些不会消耗字符,因此称为零宽断言。
八、re 模块常用函数
| 函数 | 作用 | 示例 |
|---|
re.match() | 从字符串开头匹配 | re.match('abc', 'abcdef') |
re.search() | 搜索任意位置首次匹配 | re.search('abc', '123abc456') |
re.findall() | 返回所有匹配的列表 | re.findall(r'\d+', 'a1b22c333') → ['1','22','333'] |
re.finditer() | 返回迭代器,每个元素是 Match 对象 | 遍历效率高 |
re.sub() | 替换匹配字符串 | re.sub(r'\d+', '#', 'a1b22c333') → 'a#b#c#' |
re.split() | 按匹配模式分割 | re.split(r'[,;]', 'a,b;c') → ['a','b','c'] |
re.compile() | 预编译正则,重复使用时更高效 | pattern = re.compile(r'\d+') |
九、匹配对象 Match 属性
m = re.search(r'(\d+)', 'abc123xyz')
m.group()
m.start()
m.end()
m.span()
m.groups()
十、标志位(flags)
| Flag | 含义 | 示例 |
|---|
re.I | 忽略大小写 | re.match(r'abc', 'ABC', re.I) |
re.M | 多行模式 (^,$ 匹配行首行尾) | re.findall('^abc', text, re.M) |
re.S | 让 . 匹配换行符 | re.findall('a.*b', s, re.S) |
re.X | 允许正则表达式中写注释(verbose 模式) | re.compile(r''' \d+ # 数字 ''', re.X) |
re.U | Unicode 模式(Python 3 默认开启) | 处理中文时生效 |
十一、典型应用示例
提取邮箱地址
re.findall(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}', text)
提取日期
re.findall(r'\d{4}-\d{2}-\d{2}', 'Today is 2025-10-31.')
提取 HTML 标签内容
re.findall(r'<title>(.*?)</title>', html, re.S)
匹配 IP 地址
re.findall(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', text)
替换多余空格
re.sub(r'\s+', ' ', text)
十二、性能与优化建议
| 优化点 | 建议 | | |
|---|
| 🔹 重复匹配 | 使用 re.compile() 预编译模式 | | |
| 🔹 贪婪匹配过慢 | 改为非贪婪模式 .*? | | |
| 🔹 多分支匹配 | 使用非捕获组 `(?:a | b | c)` |
| 🔹 大文本匹配 | 优先使用 finditer() 而非 findall() | | |
| 🔹 正则太复杂 | 可考虑分步匹配或 string 方法替代 | | |
十三、特殊用法
非捕获分组
(?:abc){2}
条件匹配
(?(1)then|else)
注释正则(verbose 模式)
pattern = re.compile(r'''
^\s* # 开头空白
([A-Za-z_]\w*) # 标识符
\s*=\s* # 等号
(".*?"|\d+) # 字符串或数字
''', re.X)
十四、示例汇总演示
import re
text = "Name: Tom, Email: tom@example.com, Age: 25"
email = re.search(r'[\w.-]+@[\w.-]+\.\w+', text).group()
nums = re.findall(r'\d+', text)
new_text = re.sub(r'Tom', 'Jerry', text)
parts = re.split(r',\s*', text)
pat = re.compile(r'\b[A-Z][a-z]+\b')
names = pat.findall("Tom and Alice went to London.")
十五、参考正则速查表(Cheat Sheet)
. 任意字符
^ $ 行首/行尾
\d \D 数字/非数字
\s \S 空白/非空白
\w \W 单词字符/非单词
[...] 字符集
[^...] 非字符集
(a|b) 或
(...) 捕获组
(?:...) 非捕获组
(?P<name>...) 命名捕获组
(?=...) 正向前瞻
(?!...) 负向前瞻
(?<=...) 正向后顾
(?<!...) 负向后顾
{m,n} 重复m~n次
* + ? 0+ / 1+ / 0-1 次
*? +? ?? 懒惰匹配
\b \B 单词边界 / 非边界