需處理因失誤產生的雙重副檔名,如 linzimu.apk.apk → linzimu.apk。直覺使用 rtrim($str, '.apk'),結果卻得到 linzimu —— 多刪除了 .apk 中的 a、p、k、. 所有字元。
[php]
$out = rtrim($in, '.apk');
// 實際行為:從字串尾端開始,只要字元在 ['.', 'a', 'p', 'k'] 內就持續刪除,直到遇到不在列表內的字元為止。
// "linzimu.apk.apk" → 刪除 k → 刪除 p → 刪除 a → 刪除 . → 刪除 k → 刪除 p → 刪除 a → 刪除 . → 停在 u
// 結果:"linzimu"
適用於已知要移除的子字串長度固定 (如 .apk 固定 4 字元):
[php]
$test = "linzimu.apk.apk";
$out = substr_replace($test, '', -4); // 從尾端倒數 4 字元替換為空字串
// 結果:"linzimu.apk"
$out .= '.apk'; // 若需補回單一副檔名
[php]
$test = "lin.apk.apk";
// 匹配:開頭任意字元 + .副檔名 + .副檔名 結構,捕獲第一組
preg_match("#^((.+)\.(.+))\.#i", $test, $m);
echo $m[1]; // 輸出:"lin.apk"
正則解析:
^((.+)\.(.+)):捕獲「主檔名.副檔名」作為第 1 群組\.:匹配中間的點#i:不區分大小寫[php]
$filename = "linzimu.apk.apk";
$lastDot = strrpos($filename, '.');
if ($lastDot !== false) {
$out = substr($filename, 0, $lastDot); // 取最後一個點之前
// 結果:"linzimu.apk"
}
此法最通用,不限副檔名長度,也能處理 file.tar.gz 等多點檔名。
實際專案中對 20,000+ 筆檔名去重,發現 4,000 筆檔案實體不存在。追查發現正是 rtrim 誤刪導致檔名錯誤,進而找不到實體檔。改用 strrpos + substr 後問題解決。
| 函數 | 參數語意 | 適用場景 |
|---|---|---|
| rtrim/ltrim/trim | 字元列表 (charlist) | 移除空白、特定雜訊字元 |
| substr_replace | 起始位置、長度 | 固定長度尾端替換 |
| preg_replace/preg_match | 正則模式 | 複雜模式匹配替換 |
| strrpos + substr | 字串、搜尋字元 | 通用尾端截取(推薦) |
切記:rtrim 第二參數是字元遮罩,不是子字串。 需移除尾端特定子字串時,優先使用 strrpos 定位分隔符再 substr 截取,或用 substr_replace (固定長度),複雜模式才考慮正則。