Python 正则替换与回调
替换接口把匹配到的内容换成新文本:替换内容既可以是带组引用的模板字符串,也可以是一个函数,由函数按每次匹配的结果自行决定替换成什么。模板字符串适合格式统一的改写,函数适合需要条件判断、查表或调用其他逻辑的场景,例如把匹配到的编码翻译成名称。
基本信息
| 接口签名 | sub 参数依次为模式、替换内容、待处理字符串、替换次数、标志位 |
|---|---|
| 返回差异 | sub 返回改写后的字符串,subn 额外返回替换发生的次数 |
| 替换模板 | 可以引用组,序号引用与命名引用都支持,还能引用整段匹配 |
| 回调形式 | 替换内容传函数时,函数接收一个匹配对象,返回值作为替换内容 |
典型使用场景
- 格式归一:把日期或电话号码的分隔符统一替换成一种写法
- 脱敏处理:按模式把敏感片段替换为掩码,日志与导出文件都要经过这一步
- 模板渲染:把占位符替换成实际取值,占位符名称与数据键保持一致
- 条件改写:命中不同分支时替换成不同内容,用回调函数集中处理判断
- 限制替换范围:只替换前若干处,保留其余内容不动
模板与回调写法
模板与回调写法
import re
re.sub(r'\d+', '#', 'a1b22') # 全部替换:'a#b#'
re.sub(r'\d+', '#', 'a1b22', count=1) # 只替换第一处:'a#b22'
re.subn(r'\d+', '#', 'a1b22') # ('a#b#',2):额外拿到次数
re.sub(r'(\w+)@(\w+)', r'\2@\1', 'a@b') # 交换两部分,模板建议用原始字符串
re.sub(r'(?P<k>\w+)=(?P<v>\w+)', r'\g<k>: \g<v>', 'a=1') # 命名引用
def mask(m):
return m.group(0)[:2] + '**' # 回调返回字符串作为替换内容
re.sub(r'\d{6,}', mask, text) # 需要条件判断时改用回调替换内容的形式
| 形式 | 写法要点 | 适用场合 |
|---|---|---|
| 固定文本 | 直接给字符串 | 统一替换为同一内容 |
| 序号引用 | 模板里写反斜杠加序号 | 按位置重组片段 |
| 命名引用 | 模板里写组名形式 | 模式较长时可读性更好 |
| 整段引用 | 模板里引用组 0 | 在原文前后加包装 |
| 回调函数 | 接收匹配对象,返回字符串 | 需要判断、查表或调用外部逻辑 |
替换模板里的反斜杠由正则替换语法解释,而普通字符串会先做一遍转义解释,两层叠加容易出错:写替换模板时统一使用原始字符串,可以避免绝大多数字面量与引用混淆的问题。
替换次数是从左到右计数的,因此「只替换第一处」的含义是最左边那一处,而不是最有业务意义的那一处;需要按语义挑选目标时,先用查找接口定位,再做定点替换。