re.sub()中引用捕获组最常用\1、\2等数字形式,命名组用\g更清晰,函数替换通过Match对象的group()方法获取匹配内容。

re.sub() 中用 \1、\2 引用分组最直接
匹配后想在替换字符串里复用捕获内容,最常用方式就是用反斜杠加数字:\1 表示第一个括号内的匹配,\2 是第二个,以此类推。这是正则引擎原生支持的语法,无需额外函数。
注意:数字只认 () 捕获组,不认 (?:...) 非捕获组;且编号从左到右按开括号顺序算,嵌套也一样。
-
re.sub(r"(\w+)@(\w+\.\w+)", r"[\1] at [\2]", "user@example.com")→"[user] at [example.com]" - 如果写成
r"\0",它代表整个匹配(等价于re.sub(..., r"\g", ...)),但容易和八进制转义混淆,不建议用 - 当替换字符串里要字面量输出反斜杠(比如 Windows 路径),得写双反斜杠:
r"C:\\temp\\file.txt",否则\t会被解释为制表符
用 \g 按命名组引用更清晰
当正则里有多个括号、逻辑复杂时,靠数 \1 \2 容易错。改用命名捕获组 + \g 语法,可读性和维护性高得多。
- 定义命名组用
(?P,比如...) r"(?P\d{4})-(?P \d{2})" - 替换时写
r"\g,比/\g " r"\1/\2"直观得多 - 命名组名必须是合法 Python 标识符(字母/下划线开头,只含字母数字下划线),不能是纯数字如
\g -
\g依然表示整个匹配,和\0不同,它不会被误解析为字符编码
用函数做替换时,通过 Match 对象取 .group()
当替换逻辑不能靠静态字符串搞定(比如要转大小写、查表、条件判断),就得传一个函数给 re.sub()。函数接收一个 re.Match 对象,从中调用 .group(1)、.group("name") 等方法取值。
立即学习“Python免费学习笔记(深入)”;
- 函数签名必须是
def replacer(match: re.Match) -> str:,返回替换后的字符串 -
match.group(0)是整个匹配,match.group(1)是第一捕获组,match.group("city")是命名组 - 如果某组未匹配(比如用了
?修饰且没出现),.group()会抛IndexError,要用.groupdict().get("name", "")更安全 - 示例:
re.sub(r"(\d+)", lambda m: str(int(m.group(1)) * 2), "a1b3c5")→"a2b6c10"
常见坑:转义、空匹配、Unicode 和性能
看似简单,实际踩坑不少。几个高频问题:
- 替换字符串里写
"\1"(普通双引号字符串)可能出错——Python 会先尝试把\1当 ASCII 控制字符处理。务必用原始字符串r"\1" - 正则匹配空字符串(比如
r"a*")会导致无限循环替换,re.sub()内部会跳过空匹配,但逻辑仍需警惕 - 处理中文等 Unicode 文本时,确保正则本身带
re.U标志(Python 3 默认开启,但显式写上更稳妥),否则\w可能不匹配汉字 - 大量替换时,函数式替换比字符串模板慢一截。如果只是简单拼接,优先用
r"\1...\2";复杂逻辑才上函数
真正难的不是语法,而是写对正则本身——组怎么括、要不要非贪婪、边界怎么锚定。引用只是“最后一公里”,前面没匹配准,后面全白搭。










