首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 刪除字串尾端指定子字串:rtrim 陷阱與正確替代方案

     編輯:PHP 相關知識

問題情境

需處理因失誤產生的雙重副檔名,如 linzimu.apk.apk → linzimu.apk。直覺使用 rtrim($str, '.apk'),結果卻得到 linzimu —— 多刪除了 .apk 中的 a、p、k、. 所有字元。

根本原因:rtrim 的參數是「字元列表」而非「子字串」

[php]
$out = rtrim($in, '.apk');
// 實際行為:從字串尾端開始,只要字元在 ['.', 'a', 'p', 'k'] 內就持續刪除,直到遇到不在列表內的字元為止。
// "linzimu.apk.apk" → 刪除 k → 刪除 p → 刪除 a → 刪除 . → 刪除 k → 刪除 p → 刪除 a → 刪除 . → 停在 u
// 結果:"linzimu"

正確解法三選一

方案一:substr_replace 直接替換尾端固定長度

適用於已知要移除的子字串長度固定 (如 .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:不區分大小寫

方案三:strrpos 定位最後一個點位置再截取

[php]
$filename = "linzimu.apk.apk";
$lastDot = strrpos($filename, '.');
if ($lastDot !== false) {
    $out = substr($filename, 0, $lastDot); // 取最後一個點之前
    // 結果:"linzimu.apk"
}

此法最通用,不限副檔名長度,也能處理 file.tar.gz 等多點檔名。

延伸:批次修正 2 萬筆資料的實戰教訓

實際專案中對 20,000+ 筆檔名去重,發現 4,000 筆檔案實體不存在。追查發現正是 rtrim 誤刪導致檔名錯誤,進而找不到實體檔。改用 strrpos + substr 後問題解決。

函數對照表

函數參數語意適用場景
rtrim/ltrim/trim字元列表 (charlist)移除空白、特定雜訊字元
substr_replace起始位置、長度固定長度尾端替換
preg_replace/preg_match正則模式複雜模式匹配替換
strrpos + substr字串、搜尋字元通用尾端截取(推薦)

結論

切記:rtrim 第二參數是字元遮罩,不是子字串。 需移除尾端特定子字串時,優先使用 strrpos 定位分隔符再 substr 截取,或用 substr_replace (固定長度),複雜模式才考慮正則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved