讲解
Python 的正则在标准库 re 模块里,无需安装任何东西。和 JavaScript 的概念完全对应:re.search 相当于「任意位置找第一个」,re.match 只从字符串开头试(相当于模式前自带 ^),re.fullmatch 要求整串匹配(相当于自带 ^...$),re.findall 取全部匹配,re.sub 做替换。匹配成功返回 Match 对象,用 m.group() 取整体、m.group(1) 取第 1 组;失败返回 None,判断时注意先验空。
Python 社区的铁律是模式一律用原始字符串 r'...' 书写:原始字符串里反斜杠不转义,r'\d+' 里的 \d 原样传给正则引擎;不用原始字符串的话 '\d' 恰好也能幸存,但 '\b' 会被 Python 解释成退格符,静默出错。JavaScript 的双层转义问题在 Python 里靠 r 前缀一招化解——这也是原始字符串章节值回票价的场景。
两组语法差异要留心:命名分组 Python 写作 (?P...)(JavaScript 是 (?...)),反向引用对应 \g;后顾在 Python 的 re 里必须是固定宽度,(?<=a+) 这种可变长度后顾会直接报错(JavaScript 允许)。标志位写法也不同:re.IGNORECASE、re.MULTILINE 作为参数传入,或内联写成 (?i)、(?m)。需要反复用同一个模式时 re.compile 预编译,省去重复解析。
示例
import re
# search 任意位置找第一个;match 只从开头试;fullmatch 要求整串
m = re.search(r'\d+', '订单号 A9527')
assert m is not None
print('找到:', m.group())
assert m.group() == '9527'
assert re.match(r'\d+', '订单号 A9527') is None # 开头不是数字
assert re.fullmatch(r'\w+', 'abc_123') is not None
assert re.fullmatch(r'\w+', 'abc-123') is None
import re
# findall 取全部;模式里有分组时返回的是分组内容
log = 'user=alice action=login ip=10.0.0.1'
pairs = re.findall(r'(\w+)=(\S+)', log)
print(pairs)
assert pairs == [('user', 'alice'), ('action', 'login'), ('ip', '10.0.0.1')]
assert re.findall(r'\d+', 'a1b22c333') == ['1', '22', '333']
# sub 替换,替换串里用 \1 引用分组(注意:Python 替换串用 \1 不是 $1)
masked = re.sub(r'(1\d{2})\d{4}(\d{4})', r'\1****\2', '电话 13812345678')
print(masked)
assert masked == '电话 138****5678'
import re
# compile 预编译复用;命名分组写作 (?P<name>...)
pat = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})')
m = pat.search('今天是 2026-08-09')
assert m.group('year') == '2026'
assert m.group('month') == '08'
# 固定宽度的后顾没问题
assert re.search(r'(?<=¥)\d+', '价格¥199').group() == '199'
# 标志位作为参数传入(或内联 (?i))
assert re.search(r'^cat$', 'CAT', re.IGNORECASE) is not None
assert re.findall(r'^\w+', 'one\ntwo', re.MULTILINE) == ['one', 'two']
常见坑
- 不用原始字符串:'\b' 在普通字符串里是退格符,re.findall('\bword\b', text) 永远匹配不到。模式一律写 r'...'。
- 以为 match 是「搜索」:re.match 只从开头试,等价于模式前加了 ^。日常「找一找」要用 re.search,整串校验用 re.fullmatch。
- findall 的分组行为:模式里只要有一个分组,findall 返回的就是组内容而非整体匹配。想要整体就去掉分组或改用 finditer。
- 写可变长度的后顾:Python 的 re 要求 (?<=...) 宽度固定,(?<=¥+) 直接抛 re.error。需要变长场景考虑第三方 regex 库。
小结
Python 用 re 模块:search/match/fullmatch/findall/sub 对应 JavaScript 的各方法,模式一律原始字符串,命名分组 (?P)、后顾须定长。下一节聊聊写正则的趁手工具与调试方法。