PHP strpos() 字串搜尋
strpos() 函數用來搜尋子字串在字串中第一次出現的位置。
基本用法
<?php
$str = "Hello World";
echo strpos($str, "World"); // 6
echo strpos($str, "o"); // 4
?>
語法
strpos(string $haystack, string $needle, int $offset = 0): int|false
$haystack:要搜尋的字串$needle:要尋找的子字串$offset:開始搜尋的位置(可選)- 回傳值:找到時回傳位置(從 0 開始),找不到回傳
false
注意:正確檢查結果
<?php
$str = "Hello World";
// 錯誤的判斷方式
if (strpos($str, "Hello")) { // 位置 0 會被當成 false
echo "找到了";
} else {
echo "找不到"; // 輸出:找不到(錯誤!)
}
// 正確的判斷方式
if (strpos($str, "Hello") !== false) {
echo "找到了"; // 輸出:找到了
}
?>
因為
strpos() 可能回傳 0(在位置 0 找到),一定要用 !== false 來判斷,不能只用 if (strpos(...))。使用 offset 參數
<?php
$str = "Hello Hello Hello";
echo strpos($str, "Hello"); // 0
echo strpos($str, "Hello", 1); // 6(從位置 1 開始搜尋)
echo strpos($str, "Hello", 7); // 12
?>
找出所有出現位置
<?php
function findAll(string $haystack, string $needle): array {
$positions = [];
$offset = 0;
while (($pos = strpos($haystack, $needle, $offset)) !== false) {
$positions[] = $pos;
$offset = $pos + 1;
}
return $positions;
}
$str = "Hello Hello Hello";
print_r(findAll($str, "Hello")); // [0, 6, 12]
?>
相關函數
stripos() - 不區分大小寫
<?php
$str = "Hello World";
echo strpos($str, "hello"); // false(找不到)
echo stripos($str, "hello"); // 0(找到)
echo stripos($str, "WORLD"); // 6
?>
strrpos() - 最後一次出現的位置
<?php
$str = "Hello Hello Hello";
echo strpos($str, "Hello"); // 0(第一次)
echo strrpos($str, "Hello"); // 12(最後一次)
?>
strripos() - 不區分大小寫的最後位置
<?php
$str = "Hello HELLO hello";
echo strrpos($str, "Hello"); // 0(區分大小寫)
echo strripos($str, "Hello"); // 12(不區分大小寫)
?>
常見應用
檢查子字串是否存在
<?php
$str = "Hello World";
// 使用 strpos
if (strpos($str, "World") !== false) {
echo "包含 World";
}
// PHP 8+ 使用 str_contains
if (str_contains($str, "World")) {
echo "包含 World";
}
?>
驗證 Email 格式(簡易版)
<?php
function hasAtSign(string $email): bool {
return strpos($email, '@') !== false;
}
var_dump(hasAtSign("user@example.com")); // true
var_dump(hasAtSign("invalid-email")); // false
?>
解析 URL
<?php
$url = "https://example.com/path/to/file";
// 取得協定
$protocolEnd = strpos($url, '://');
$protocol = substr($url, 0, $protocolEnd);
echo $protocol; // "https"
// 取得域名
$domainStart = $protocolEnd + 3;
$domainEnd = strpos($url, '/', $domainStart);
$domain = substr($url, $domainStart, $domainEnd - $domainStart);
echo $domain; // "example.com"
?>
取得檔案副檔名
<?php
function getExtension(string $filename): string {
$pos = strrpos($filename, '.');
if ($pos === false) {
return '';
}
return substr($filename, $pos + 1);
}
echo getExtension("document.pdf"); // "pdf"
echo getExtension("archive.tar.gz"); // "gz"
echo getExtension("no-extension"); // ""
?>
關鍵字高亮
<?php
function highlight(string $text, string $keyword): string {
$pos = stripos($text, $keyword);
if ($pos === false) {
return $text;
}
$before = substr($text, 0, $pos);
$match = substr($text, $pos, strlen($keyword));
$after = substr($text, $pos + strlen($keyword));
return $before . "<mark>$match</mark>" . $after;
}
echo highlight("Hello World", "world");
// Hello <mark>World</mark>
?>
計算子字串出現次數
<?php
function countOccurrences(string $haystack, string $needle): int {
$count = 0;
$offset = 0;
while (($pos = strpos($haystack, $needle, $offset)) !== false) {
$count++;
$offset = $pos + 1;
}
return $count;
}
echo countOccurrences("Hello Hello Hello", "Hello"); // 3
// 使用內建函數
echo substr_count("Hello Hello Hello", "Hello"); // 3
?>
PHP 8+ 新函數
str_contains() - 檢查是否包含
<?php
$str = "Hello World";
// 舊寫法
if (strpos($str, "World") !== false) { }
// PHP 8+
if (str_contains($str, "World")) { }
?>
str_starts_with() - 檢查開頭
<?php
$str = "Hello World";
// 舊寫法
if (strpos($str, "Hello") === 0) { }
// PHP 8+
if (str_starts_with($str, "Hello")) { }
?>
str_ends_with() - 檢查結尾
<?php
$str = "Hello World";
// 舊寫法
if (substr($str, -5) === "World") { }
// PHP 8+
if (str_ends_with($str, "World")) { }
?>
效能考量
<?php
$longString = str_repeat("Hello World ", 10000);
// strpos 在找到後會立即停止,效率高
$start = microtime(true);
$pos = strpos($longString, "World");
$time1 = microtime(true) - $start;
// 正規表示式通常較慢
$start = microtime(true);
preg_match('/World/', $longString, $matches);
$time2 = microtime(true) - $start;
// strpos 通常比 preg_match 快
?>