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

PHP 字串截取函式完整比較:substr、mb_substr、mb_strcut 差異與選擇指南

     編輯:PHP 相關知識

前言

字串截取是高頻操作,但 `substr` 遇到中文會產生亂碼,`mb_substr` 與 `mb_strcut` 雖支援多位元組,卻因「字元」與「位元組」單位不同而導致結果差異。本文深度比較三函式機制、實測案例、選擇指南與封裝建議。

函式簽名與核心差異

函式簽名單位多位元組安全半字元處理適用場景
substrsubstr(string, start, length)位元組❌直接切半 → 亂碼純 ASCII、二進位資料
mb_substrmb_substr(string, start, length, encoding)**字元**✅不切半字元**一般文字截取、摘要、標題**
mb_strcutmb_strcut(string, start, length, encoding)**位元組**✅從字元邊界開始切,不產生半字元固定位元組長度輸出(如 DB CHAR 欄位)

實測案例(UTF-8)

$s = '這樣一來我的字符串就不會有亂碼^_^';

echo "mb_substr(0,7): " . mb_substr($s, 0, 7, 'utf-8') . "\n"; // 這樣一來我的字  (7 字元)
echo "mb_strcut(0,7): " . mb_strcut($s, 0, 7, 'utf-8') . "\n"; // 這樣一          (7 位元組 ≈ 2.3 字元)

$s2 = '飛花院博客feihuayuan';
echo "mb_substr(0,9): " . mb_substr($s2, 0, 9, 'utf-8') . "\n"; // 飛花院博客feih (9 字元)
echo "mb_strcut(0,9): " . mb_strcut($s2, 0, 9, 'utf-8') . "\n"; // 飛花院       (9 位元組 = 3 中文字)

$s3 = '我是一串比較長的中文-';
echo "mb_substr(0,6): " . mb_substr($s3, 0, 6, 'utf-8') . "\n"; // 我是一串比較
echo "mb_strcut(0,6): " . mb_strcut($s3, 0, 6, 'utf-8') . "\n"; // 我是

參數細節

  • start:正數 = 從開頭第 N 個單位;負數 = 從結尾倒數第 N 個單位(`mb_substr` 為字元、`mb_strcut` 為位元組)。
  • length:正數 = 截取長度;負數 = 從結尾排除長度;省略 = 截取到結尾。
  • encoding**:省略時使用 `mb_internal_encoding()` 設定值,**強烈建議顯式傳入 `'UTF-8'`**。

mb_strcut 邊界行為詳解

$s = '中文abc'; // UTF-8: 中(3) 文(3) a(1) b(1) c(1) = 9 bytes

mb_strcut($s, 0, 1); // ''   (第 1 byte 非字元邊界,退到字元開頭 → 0 長度)
mb_strcut($s, 0, 2); // ''   (同理)
mb_strcut($s, 0, 3); // '中' (剛好 1 個中文字元)
mb_strcut($s, 0, 4); // '中' (第 4 byte 屬於「文」字元,退到「文」開頭 → 仍只取「中」)
mb_strcut($s, 0, 6); // '中文' (2 個中文字元 = 6 bytes)

**規則**:`mb_strcut` 會將 `start` 向前調整到最近的字元邊界,再截取 `length` 位元組,最後再向後調整結束位置到字元邊界。**保證不產生半個字元**。

選擇指南

  1. **一般文字截取(標題、摘要、顯示截斷)** → `mb_substr($str, 0, $len, 'UTF-8')`**
  2. **固定位元組長度輸出(資料庫 CHAR、二進位協定、舊系統介接)** → `mb_strcut($str, 0, $bytes, 'UTF-8')`**
  3. **純 ASCII / 位元組操作** → `substr`(最快)
  4. **需同時支援 UTF-8/GBK** → 統一轉 UTF-8 後用 `mb_substr`,或依編碼動態傳入 encoding 參數。

封裝建議:安全截斷工具函式

/**
 * 多位元組安全截斷(按字元數)
 */
function mb_truncate($string, $length, $etc = '...', $encoding = 'UTF-8') {
    if (mb_strlen($string, $encoding) <= $length) return $string;
    $etcLen = mb_strlen($etc, $encoding);
    $cutLen = max(0, $length - $etcLen);
    return mb_substr($string, 0, $cutLen, $encoding) . $etc;
}

/**
 * 固定位元組截斷(不產生半字元)
 */
function mb_cut_bytes($string, $bytes, $encoding = 'UTF-8') {
    return mb_strcut($string, 0, $bytes, $encoding);
}

// 使用
echo mb_truncate('這是一個很長的標題需要截斷', 10); // 這是一個很長的...
echo mb_cut_bytes('中文abc', 6); // 中文

總結

**`mb_substr` 按字元截取,`mb_strcut` 按位元組截取**,兩者皆保證不產生半個字元。**90% 場景用 `mb_substr`**;只有「必須輸出固定位元組長度」才用 `mb_strcut`。專案統一 UTF-8、設定 `mb_internal_encoding('UTF-8')`、封裝工具函式,即可徹底解決中文截取亂碼問題。

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