將字符串按分隔符切分為數組是高頻操作。PHP 提供 explode(固定分隔符)、preg_split(正則分隔符)、str_split(固定長度)、mb_split(多字節正則)四大函數。本文對比性能、編碼支援、邊界行為,給出選型建議。
| 函數 | 分隔符類型 | 編碼感知 | 性能 | 典型用途 |
|---|---|---|---|---|
| explode | 固定字符串 | ❌ 字節級 | ⚡ 最快 | CSV、路徑、簡單標記分割 |
| preg_split | PCRE 正則 | ❌ 字節級(除非 /u) | 🐢 較慢 | 多種分隔符、複雜模式、去除空元素 |
| mb_split | 正則(mbstring) | ✅ 字符級 | 🐢 慢 | 多字節語言正則分割 |
| str_split | 固定長度 | ❌ 字節級 | ⚡ 快 | 字符串轉字符陣列、定長切片 |
<?php
$csv = 'apple,banana,orange,grape';
$arr = explode(',', $csv);
// ['apple','banana','orange','grape']
// 限制返回元素數(最後一元素包含剩餘部分)
$str = 'a,b,c,d,e';
explode(',', $str, 3); // ['a','b','c,d,e']
explode(',', $str, -2); // 負數:返回除最後 2 個外的所有 ['a','b','c']
// 邊界:空字符串返回 [''],非空分隔符不在字符串中返回 [原字符串]
explode('|', ''); // ['']
explode('|', 'abc'); // ['abc']
?>
<?php
// 多種分隔符:逗號、分號、空白
$str = 'apple, banana; orange grape';
$arr = preg_split('/[,;\s]+/', $str); // ['apple','banana','orange','grape']
// PREG_SPLIT_NO_EMPTY:過濾空元素
$str = 'a,,b,,c';
preg_split('/,/', $str); // ['a','','b','','c']
preg_split('/,/', $str, -1, PREG_SPLIT_NO_EMPTY); // ['a','b','c']
// PREG_SPLIT_DELIM_CAPTURE:保留分隔符
preg_split('/(\s+)/', 'a b c', -1, PREG_SPLIT_DELIM_CAPTURE);
// ['a', ' ', 'b', ' ', 'c']
// PREG_SPLIT_OFFSET_CAPTURE:返回 [元素, 偏移量]
preg_split('/,/', 'a,b', -1, PREG_SPLIT_OFFSET_CAPTURE);
// [['a',0], [',',1], ['b',2]]
// 正則修飾符:/u 支援 UTF-8 字符邊界
$zh = '你好,世界';
preg_split('/,/u', $zh); // ['你好','世界'] 正確
preg_split('/,/', $zh); // 字節級切分,可能破壞多字節字符
?>
<?php
// 按中文標點分割
$text = '你好。世界!再見?';
$arr = mb_split('[。!?]', $text); // ['你好', '世界', '再見', '']
// 等同 preg_split('/[。!?]/u', $text) 但語義更明確
?>
<?php
$str = 'Hello';
str_split($str); // ['H','e','l','l','o'] 長度 1
str_split($str, 2); // ['He','ll','o'] 長度 2
// 注意:字節級切分,UTF-8 中文會被拆分
$zh = '你好';
str_split($zh, 1); // ['你'的前半字節, '你'的後半字節, '好'的前半...] ❌
// 正確:mb_str_split (PHP 7.4+) 或 preg_split('//u')
mb_str_split($zh); // ['你','好'] ✅
?>
<?php
$str = 'a,b,c,d,e,f,g,h,i,j';
$iter = 1_000_000;
$t = microtime(true);
for($i=0;$i<$iter;$i++) explode(',', $str);
echo "explode: " . (microtime(true)-$t) . "s\n"; // ~0.08s
$t = microtime(true);
for($i=0;$i<$iter;$i++) preg_split('/,/', $str);
echo "preg_split: " . (microtime(true)-$t) . "s\n"; // ~0.45s
$t = microtime(true);
for($i=0;$i<$iter;$i++) str_split($str, 1);
echo "str_split: " . (microtime(true)-$t) . "s\n"; // ~0.12s
?>
需要分割字符串? ├─ 分隔符是固定字符串(單字符或多字符) → explode() 首選 ├─ 分隔符是多種/複雜模式(如:空白、標點混合) → preg_split() ├─ 多字節語言(中文/日文/韓文)按正則分割 → mb_split() 或 preg_split(..., /u) ├─ 固定長度切片(如:每 4 位分組) → str_split() / mb_str_split() └─ 解析 CSV → 專用 fgetcsv() / str_getcsv()(處理引號、轉義)
<?php
$log = '2024-01-15 10:30:45 [INFO] UserController@login - User "john_doe" logged in from 192.168.1.100';
// 正則提取結構化字段
$pattern = '/^(\S+ \S+) \[(\w+)\] (\S+) - (.+)$/';
if (preg_match($pattern, $log, $m)) {
[$_, $datetime, $level, $context, $message] = $m;
echo "時間: $datetime\n級別: $level\n上下文: $context\n訊息: $message\n";
}
?>