str_replace()适用于固定字符串的批量字面替换,支持数组参数、从左到右全部匹配,不区分单词边界且大小写敏感;需用str_ireplace()忽略大小写,正则场景应选preg_replace()。

用 str_replace() 做简单批量替换最直接
多数场景下,你要的只是把几个固定字符串替换成别的,比如把日志里的 DEBUG 全改成 INFO,或清理用户输入里的敏感词。这时候 str_replace() 不仅快,而且语义清晰、无正则开销。
它支持数组参数,一次传入多个搜索项和替换项,顺序严格对应:
$text = "apple banana apple cherry"; $result = str_replace(['apple', 'banana'], ['orange', 'grape'], $text); // 输出:orange grape orange cherry
注意:替换是「全部匹配、从左到右」执行的,不是原子性替换。如果 search 数组里有重叠项(比如 ['a', 'aa']),短的会先被换掉,可能影响后续匹配 —— 这不是 bug,是设计行为。
- 别把
str_replace()当成“安全过滤”用:它不区分单词边界,str_replace(['admin'], ['***'], 'administrator')会变成***istrator - 大小写敏感,要忽略大小写请改用
str_ireplace() - 如果搜索项含正则元字符(如
.、*),它不会解释为正则,而是按字面匹配 —— 这反而是优点,不用转义
需要模式匹配时,preg_replace() 才是正确选择
当你得按格式替换,比如「所有 4 位数字」或「邮箱里的 @ 后域名部分」,就必须上正则。这时候硬套 str_replace() 会写出一堆脆弱逻辑,还容易漏边角情况。
立即学习“PHP免费学习笔记(深入)”;
preg_replace() 的第一个参数是正则模式,第二个是替换内容,支持反向引用($1、$2):
$text = "Contact: a@b.com or x@y.org";
$result = preg_replace('/([a-z]+)@([a-z]+\.[a-z]+)/i', '$1@***', $text);
// 输出:Contact: a@*** or x@***常见坑点:
- 忘记加分隔符(如
/或#),PHP 会报PREG_NO_DELIMITER错误 - 模式里用了
/却没转义,比如匹配路径/user/(\d+)/写成'/user/(\d+)/'没问题,但若变量拼接进来,$path = '/user'; preg_replace("/$path\/(\d+)/", ...)就得手动处理斜杠 - 性能敏感场景慎用复杂正则,尤其是带回溯的(如
.*配合可选量词),可能引发「灾难性回溯」,CPU 瞬间拉满
替换前要判断是否存在?别先 strpos() 再 str_replace()
有人习惯先用 strpos() 检查字符串里有没有目标,再决定是否替换。这纯属多一次扫描 —— str_replace() 本身返回新字符串,且内部实现就是边扫边换,调用一次就够了。
更糟的是,如果用 strpos() 判断后又用 str_replace(),中间字符串若被其他代码修改(比如引用传递或全局变量),结果就不可靠。PHP 字符串是值语义,但逻辑上没必要拆成两步。
- 想确认是否发生了替换?对比原字符串和结果:
$replaced = str_replace(...); if ($replaced !== $original) { ... } - 想统计替换了几次?用
str_replace()的第四个参数(引用变量):str_replace($search, $replace, $text, $count); // $count 被赋值为替换次数 - 别为了「省一点 CPU」提前判断,现代 PHP 对空替换优化很好,没你想的那么重
多维数组里批量替换字符串,别手写递归
遇到配置数组、API 返回数据这类嵌套结构,想把所有字符串值里的某个词替换掉,最容易犯的错是写个 for 循环套 if + is_string 判断,再层层进子数组 —— 既啰嗦又容易漏掉对象或资源类型。
更稳的方式是用 array_walk_recursive(),它自动跳过非标量值(对象、资源、数组本身),只对叶子节点的字符串/数字等调回调函数:
function replace_in_array(&$item, $key) {
if (is_string($item)) {
$item = str_replace('old', 'new', $item);
}
}
array_walk_recursive($config, 'replace_in_array');注意限制:
- 它不处理键名,只处理值;如果也要替换键名,得另写逻辑
- 遇到对象属性,它进不去(除非对象实现了
Iterator),所以 JSON 解码后的 stdClass 对象不会被遍历到字符串属性 - 如果数组里混着对象且你真需要处理,用
json_encode() → str_replace() → json_decode()是更粗暴但有效的兜底方案,前提是数据不含二进制或特殊控制字符
实际批量替换没那么多花样,关键是分清「字面替换」和「模式替换」——前者死守 str_replace() 或 str_ireplace(),后者闭眼用 preg_replace()。至于嵌套结构,优先走 array_walk_recursive(),别自己造轮子去猜数据形状。











