四大核心函數對照表
| 函數 | 方向 | 大小寫 | 回傳值 | 適用場景 |
strstr() | 左→右 | 敏感 | 子字串~結尾 (含針) | 提取後綴、檢查是否包含 |
stristr() | 左→右 | 不敏感 | 子字串~結尾 | 不分大小寫檢查/提取 |
strrchr() | 右→左 | 敏感 | 最後匹配字元~結尾 | 取副檔名、最後一段路徑 |
strpos() | 左→右 | 敏感 | 位置索引 (int) / false | 高效判斷包含、定位位置 |
stripos() | 左→右 | 不敏感 | 位置索引 | 不分大小寫定位 |
strrpos() | 右→左 | 敏感 | 最後位置索引 | 找最後一次出現位置 |
實戰範例
<?php
$text = '天高任鳥飛,海闊憑魚躍';
// strstr:從左找,回傳含針的後段
echo strstr($text, ','); // ,海闊憑魚躍
echo strstr($text, '鳥飛'); // 鳥飛
// strrchr:從右找字元 (注意:第二參數只取首字元)
$eng = 'I have a great dream.';
echo strrchr($eng, 'e'); // eam. (最後一個 e 到結尾)
echo strrchr($eng, 've'); // veam. (只拿 'v' 做匹配!)
// strpos:高效定位位置 (必須用 !== false 判斷)
$abstract = 'I am an abstract about abroad.';
echo strpos($abstract, 'ab'); // 8 (第一個 ab)
echo strpos($abstract, 'ab', 9); // 22 (從索引 9 開始找)
// strrpos:找最後位置
$wang = 'I am is wang hui.';
echo strrpos($wang, 'I'); // 0 (大寫 I)
echo strrpos($wang, 'i'); // 15 (小寫 i 最後位置)
echo strrpos($wang, 'an'); // 5 (an 最後位置)
?>
關鍵陷阱:0 vs false
<?php
$str = 'hello world';
// ❌ 錯誤:0 會被當作 false
if (strpos($str, 'h')) { echo 'Found'; } // 不會執行!因為位置 0 是 false
// ✅ 正確:嚴格比較
if (strpos($str, 'h') !== false) { echo 'Found at 0'; }
// ✅ PHP 8.0+ 新函數:更直觀
if (str_contains($str, 'h')) { echo 'Contains'; } // 包含檢查
if (str_starts_with($str, 'he')) { echo 'Starts with'; } // 開頭檢查
if (str_ends_with($str, 'ld')) { echo 'Ends with'; } // 結尾檢查
?>
效能對比
<?php
$haystack = str_repeat('abcdefghijklmnopqrstuvwxyz ', 10000); // ~270KB
$needle = 'xyz';
$iterations = 1000;
$start = hrtime(true);
for ($i=0; $i<$iterations; $i++) strpos($haystack, $needle);
echo "strpos: " . (hrtime(true)-$start)/1e6/$iterations . " ms\n";
$start = hrtime(true);
for ($i=0; $i<$iterations; $i++) strstr($haystack, $needle);
echo "strstr: " . (hrtime(true)-$start)/1e6/$iterations . " ms\n";
$start = hrtime(true);
for ($i=0; $i<$iterations; $i++) preg_match('/' . $needle . '/', $haystack);
echo "preg_match: " . (hrtime(true)-$start)/1e6/$iterations . " ms\n";
/* 典型輸出:
strpos: 0.012 ms
strstr: 0.018 ms
preg_match: 0.085 ms
結論:單純查找用 strpos/stripos 最快,需提取子串用 strstr,複雜模式才用正則
*/
?>
多位元組字串 (中文) 處理
<?php
$zh = '天高任鳥飛,海闊憑魚躍';
// 必須用 mb_* 系列,指定編碼
echo mb_strpos($zh, '鳥'); // 6 (字元索引,非位元組)
echo mb_strrpos($zh, '海'); // 9
echo mb_strstr($zh, '海'); // 海闊憑魚躍
echo mb_substr($zh, 4, 3); // 鳥飛,
// 內部編碼設定 (影響所有 mb_* 函數)
mb_internal_encoding('UTF-8');
?>
最佳實踐選擇指南
- 只需判斷是否包含:
str_contains() (PHP 8.0+) 或 strpos() !== false
- 需提取匹配後內容:
strstr() / mb_strstr()
- 需提取匹配前內容:
strstr($hay, $needle, true) (PHP 5.3+)
- 找最後一次出現:
strrpos() / strripos()
- 取副檔名/最後路徑段:
pathinfo($path, PATHINFO_EXTENSION) 或 basename() 優於 strrchr()
- 中文/多語言:全程使用
mb_* 系列,設定 mb_internal_encoding('UTF-8')