常見需求:移除字串開頭的 akmumu/ 與結尾的 .json,保留中間實際路徑 /writedb。直接使用 ltrim()/rtrim() 會踩中「字元清單模式」陷阱,導致過度截斷。本文說明陷阱成因,提供安全、語意精確的解法。
$str = 'akmumu/writedbsojn.json';
// 錯誤做法:trim 視參數為「字元清單」,而非「子字串」
$r = rtrim($str, '.json'); // 結果:'akmumu/writedbso' (把 n、s、o、j 都當作可移除字元)
$l = ltrim($r, 'akmumu/'); // 結果:'writedbso' (把 a、k、m、u、/ 都移除)
trim($str, $charlist) 會移除「出現在 charlist 中的任意字元」,直到遇到不在清單內的字元為止,不保證順序、不匹配整體子字串。
<?php
$str = 'akmumu/writedb.json';
$prefix = 'akmumu/';
$suffix = '.json';
// 1. 移除前綴
if (strpos($str, $prefix) === 0) { // 嚴格判斷「開頭就是」
$str = substr($str, strlen($prefix)); // 截掉前綴長度
}
// 2. 移除後綴
$suffixLen = strlen($suffix);
if (strlen($str) >= $suffixLen && substr($str, -$suffixLen) === $suffix) {
$str = substr($str, 0, -$suffixLen); // 截掉後綴長度
}
echo $str; // 輸出:/writedb
/**
* 移除字串開頭的特定前綴
*/
function remove_prefix(string $str, string $prefix): string
{
if ($prefix !== '' && strpos($str, $prefix) === 0) {
return substr($str, strlen($prefix));
}
return $str;
}
/**
* 移除字串結尾的特定後綴
*/
function remove_suffix(string $str, string $suffix): string
{
$len = strlen($suffix);
if ($len > 0 && strlen($str) >= $len && substr($str, -$len) === $suffix) {
return substr($str, 0, -$len);
}
return $str;
}
/**
* 同時移除前後綴
*/
function trim_affix(string $str, string $prefix = '', string $suffix = ''): string
{
$str = remove_prefix($str, $prefix);
$str = remove_suffix($str, $suffix);
return $str;
}
// 使用範例
$path = 'akmumu/writedbsojn.json';
echo trim_affix($path, 'akmumu/', '.json'); // /writedbsojn
// 多層路徑範例
$url = 'https://example.com/api/v1/users.json';
echo trim_affix($url, 'https://example.com', '.json'); // /api/v1/users
// 移除開頭固定前綴
$str = preg_replace('/^' . preg_quote('akmumu/', '/') . '/', '', $str);
// 移除結尾固定後綴
$str = preg_replace('/' . preg_quote('.json', '/') . '$/', '', $str);
// 一次完成
$str = preg_replace(
['/^' . preg_quote('akmumu/', '/') . '/', '/' . preg_quote('.json', '/') . '$/'],
'',
$str
);
正則優點:可處理複雜模式(如可選前綴、多種後綴)。缺點:效能較低、可讀性稍差。
// PHP 8.0+ 才有
$str = 'akmumu/writedb.json';
$str = str_starts_with($str, 'akmumu/') ? substr($str, 7) : $str;
$str = str_ends_with($str, '.json') ? substr($str, 0, -5) : $str;
str_starts_with()/str_ends_with() 語意清晰、效能佳,建議 PHP 8+ 專案優先使用。
| 方法 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
trim/ltrim/rtrim | 移除首尾單一字元集合(空白、換行、特定符號) | 內建、快速 | 不支援子字串匹配,易誤用 |
strpos + substr | 精確移除固定前綴/後綴子字串 | 語意精確、相容所有 PHP 版本 | 程式碼較冗長 |
preg_replace | 模式化前綴/後綴(可選、多選一) | 彈性強 | 效能較差、需注意跳脫 |
str_starts_with/str_ends_with | PHP 8.0+ 環境,精確判斷開頭/結尾 | 語意明確、可讀性最佳 | 需 PHP 8.0+ |