測試環境與資料
$str = '111111110000000000000000000000000000000111000001000100010000010010000010010000010100000010';
$str = str_repeat($str, 1); // 或 8 倍長度測試
$pattern1 = ['12345'=>'', '67891'=>'']; // 短鍵
$pattern2 = ['a'=>'', '1234567890'=>'']; // 長短鍵混合
$pattern3 = '/12345|67891/';
$pattern4 = '/a|1234567890/';
$pattern5 = ['12345', '67891'];
$pattern6 = ['a', '1234567890'];
效能測試結果(10,000 次迴圈)
| 函數 | 模式 | 短字串 (x1) | 長字串 (x8) | 相對效能 |
strtr | $pattern1 (等長短鍵) | 0.22s | 0.47s | 基準 |
strtr | $pattern2 (長短混合) | 0.48s | 2.73s | ↓ 5-6x 慢 |
preg_replace | $pattern3 | 0.31s | 1.09s | ~1.4-2.3x |
preg_replace | $pattern4 | 0.30s | 1.12s | ~1.4-2.4x |
str_replace | $pattern5 | 0.18s | 0.23s | 最快 (基準 1x) |
str_replace | $pattern6 | 0.18s | 0.23s | 最快穩定 |
核心結論
- str_replace 綜合效能最佳:實作為依序遍歷 search 陣列,在 subject 中查找替換,無額外開銷。
- strtr 陣列模式效能極不穩定:內部建立長度索引表,從最長鍵遞減匹配,鍵長度差異大時開銷劇增。
- preg_replace 功能最強但較慢:正則引擎開銷固定,適合複雜模式。
行為差異關鍵:最大匹配 vs 順序匹配
$subject = 'abcd';
$search = ['ab', 'abc'];
$replace = '1';
// strtr:最大匹配優先 → 'abcd' 匹配 'abc' → '1d'
echo strtr($subject, array_combine($search, [$replace, $replace])); // 1d
// str_replace:順序匹配 → 先替換 'ab' → '1cd'
echo str_replace($search, $replace, $subject); // 1cd
使用建議
| 場景 | 推薦函數 | 注意事項 |
| 簡單字串替換、固定詞彙 | str_replace | 將優先匹配項放前面 |
| 單字元/位元組映射轉換 | strtr($str, $from, $to) | 三參數版本極快,但僅限單位元組字元,中文易亂碼 |
| 鍵值對替換、鍵長度相近 | strtr($str, $pairs) | 避免鍵長度差異過大 |
| 模式匹配、提取、複雜替換 | preg_replace | 善用預編譯、非捕獲組優化 |
| 大量固定字串替換(如敏感詞過濾) | str_replace + array | 可預先排序 search 陣列(長優先)模擬最大匹配 |
原始碼層面洞察
str_replace:遍歷 search 陣列,對每個 needle 在 haystack 中 php_str_to_str() 查找替換(Boyer-Moore/Horspool)
strtr 陣列模式:php_strtr_array() 建立長度索引表,從最大長度遞減掃描 subject,HashTable 查找鍵
preg_replace:PCRE 引擎編譯正則,JIT 優化(PHP 7.3+)