PHP 正则替换回调与引用
替换有两种入口:直接给替换字符串时按模板语法引用分组,交给回调函数时由代码决定每次匹配替换成什么。历史上用模式修饰符让替换内容被当作代码执行的做法早已被移除,取而代之的就是回调形式,因此凡是要根据匹配内容做判断、查表或计算的场景,都应当使用回调。
基本信息
| 模板替换 | 替换字符串中可用序号形式引用捕获组,命名组用带名字的形式引用 |
|---|---|
| 回调替换 | 回调接收一个匹配数组,结构与单次匹配结果一致,返回值作为替换内容 |
| 替换次数限制 | 参数可限制替换的最大次数,默认全部替换 |
| 出错返回 | 替换失败时返回空值而不是空字符串,必须与替换后为空区分 |
典型使用场景
- 脱敏改写:按匹配内容做掩码,保留前后部分而隐藏中间内容
- 格式转换:把匹配到的编码或标识翻译成名称,需要查表时用回调
- 条件替换:只对满足额外条件的匹配做改写,其余保持原样
- 批量规则:把多组模式与处理函数配对,一次遍历完成多类替换
- 计数统计:借助额外的计数参数统计实际替换次数并写入指标
模板与回调写法
模板与回调写法
$s = 'a1b2';
preg_replace('/\d/', '#', $s); // 'a#b#':全部替换
preg_replace('/(\w)(\d)/', '$2$1', $s); // 交换两部分,按序号引用
preg_replace('/(?<k>\w+)=(?<v>\w+)/', '${k}: ${v}', 'a=1'); // 按名字引用
$count = 0;
preg_replace('/\d/', '#', $s, -1, $count); // 通过引用参数取出替换次数
preg_replace_callback('/\d+/', function ($m) { // 回调决定替换内容
return (string) ((int) $m[0] * 2);
}, $s);
// 多组规则一次完成:模式到回调的映射形式
preg_replace_callback_array(['/\d/' => fn($m) => '#'], $s);两种替换入口对照
| 入口 | 引用方式 | 适用场合 |
|---|---|---|
| 模板替换 | 序号与命名分组引用 | 格式固定、无需判断 |
| 回调替换 | 代码读取匹配数组 | 需要条件判断或查表 |
| 多规则替换 | 模式与回调配对 | 一次遍历完成多类改写 |
| 次数限制参数 | 控制替换上限 | 只替换前若干处 |
回调返回值会被转换成字符串写入结果;返回空值会得到空内容,等于把匹配内容删掉,需要保留原样时应显式返回整体匹配内容。
替换失败的返回值与结果为空字符串在宽松判断下无法区分,工程代码应当严格比较返回值,并在失败时读取正则错误码定位原因。