PHP substr() 字串擷取
substr() 函數用來擷取字串的一部分。
基本用法
<?php
$str = "Hello World";
echo substr($str, 0, 5); // "Hello"
echo substr($str, 6); // "World"
?>
語法
substr(string $string, int $offset, ?int $length = null): string
$string:原始字串$offset:開始位置(從 0 開始)$length:要擷取的長度(可選)- 回傳值:擷取的子字串,失敗時回傳空字串(PHP 8)或
false(PHP 7)
使用正數 offset
<?php
$str = "Hello World";
// 01234567890
echo substr($str, 0); // "Hello World"(從頭開始)
echo substr($str, 1); // "ello World"
echo substr($str, 6); // "World"
echo substr($str, 0, 5); // "Hello"
echo substr($str, 6, 5); // "World"
echo substr($str, 0, 1); // "H"
?>
使用負數 offset
負數 offset 從字串尾端算起:
<?php
$str = "Hello World";
echo substr($str, -5); // "World"(從倒數第 5 個開始)
echo substr($str, -5, 3); // "Wor"
echo substr($str, -1); // "d"(最後一個字元)
?>
使用負數 length
負數 length 表示要排除尾端的字元數:
<?php
$str = "Hello World";
echo substr($str, 0, -1); // "Hello Worl"(排除最後 1 個字元)
echo substr($str, 0, -6); // "Hello"(排除最後 6 個字元)
echo substr($str, 2, -2); // "llo Wor"
?>
組合使用
<?php
$str = "Hello World";
// 從倒數第 5 個開始,擷取到倒數第 1 個(不含)
echo substr($str, -5, -1); // "Worl"
// 從第 2 個開始,擷取到倒數第 3 個(不含)
echo substr($str, 2, -3); // "llo Wo"
?>
邊界情況
<?php
$str = "Hello";
// offset 超過字串長度
echo substr($str, 10); // ""(PHP 8)或 false(PHP 7)
// length 超過剩餘長度
echo substr($str, 2, 100); // "llo"(自動調整)
// 空字串
echo substr("", 0, 5); // ""
?>
中文字串使用 mb_substr()
substr() 以位元組為單位,處理中文需要使用 mb_substr():
<?php
$str = "你好世界";
// substr 會切斷中文字
echo substr($str, 0, 3); // "你"(剛好 3 bytes)
echo substr($str, 0, 4); // 亂碼(切斷了一個中文字)
// mb_substr 以字元為單位
echo mb_substr($str, 0, 2); // "你好"
echo mb_substr($str, 2); // "世界"
echo mb_substr($str, -1); // "界"
?>
常見應用
取得檔案副檔名
<?php
$filename = "document.pdf";
// 使用 substr
$ext = substr($filename, strrpos($filename, '.') + 1);
echo $ext; // "pdf"
// 更簡潔的方式
$ext = pathinfo($filename, PATHINFO_EXTENSION);
?>
隱藏部分資訊
<?php
function maskEmail(string $email): string {
$atPos = strpos($email, '@');
if ($atPos === false || $atPos < 2) {
return $email;
}
$firstChar = substr($email, 0, 1);
$domain = substr($email, $atPos);
$maskedLength = $atPos - 1;
return $firstChar . str_repeat('*', $maskedLength) . $domain;
}
echo maskEmail("alice@example.com"); // a****@example.com
function maskPhone(string $phone): string {
return substr($phone, 0, 4) . '****' . substr($phone, -2);
}
echo maskPhone("0912345678"); // 0912****78
?>
截斷文字
<?php
function truncate(string $text, int $length = 100, string $suffix = '...'): string {
if (mb_strlen($text) <= $length) {
return $text;
}
return mb_substr($text, 0, $length) . $suffix;
}
echo truncate("這是一段很長的文字", 5); // 這是一段很...
?>
取得子字串
<?php
$url = "https://example.com/path/to/file";
// 取得協定
$protocol = substr($url, 0, strpos($url, '://'));
echo $protocol; // "https"
// 取得域名
$start = strpos($url, '://') + 3;
$end = strpos($url, '/', $start);
$domain = substr($url, $start, $end - $start);
echo $domain; // "example.com"
?>
格式化字串
<?php
// 信用卡號格式化
function formatCreditCard(string $number): string {
$number = preg_replace('/\D/', '', $number);
return substr($number, 0, 4) . ' ' .
substr($number, 4, 4) . ' ' .
substr($number, 8, 4) . ' ' .
substr($number, 12, 4);
}
echo formatCreditCard("1234567890123456"); // 1234 5678 9012 3456
?>
與其他函數比較
| 函數 | 說明 |
|---|---|
substr() | 擷取子字串(位元組) |
mb_substr() | 擷取子字串(字元) |
substr_replace() | 取代子字串 |
strstr() | 取得第一次出現後的部分 |
<?php
$str = "Hello World";
echo substr($str, 6); // "World"
echo strstr($str, " "); // " World"(包含分隔符)
echo strstr($str, " ", true); // "Hello"(分隔符之前)
?>
效能考量
substr() 會建立新字串,不會修改原字串:
<?php
$str = "Hello World";
$sub = substr($str, 0, 5);
echo $str; // "Hello World"(原字串不變)
echo $sub; // "Hello"
?>