PCRE(Perl Compatible Regular Expressions)是 PHP 處理複雜字串模式比對、擷取、替換與分割的核心工具。本文系統整理 preg_match、preg_match_all、preg_replace、preg_split 四大函數的語法、參數、修飾符與實戰範例,並對比同功能的非正則函數效能差異。
| 函數 | 用途 | 回傳值 | 典型場景 |
|---|---|---|---|
preg_match | 比對一次,找到即停止 | int (0/1/false),$matches 為參考參數 | 驗證格式、擷取第一組 |
preg_match_all | 全域比對所有符合項 | int 比對次數,$matches 多維陣列 | 擷取所有連結、關鍵字 |
preg_replace | 模式替換,支援陣列與回呼 | string|array 替換後字串 | 樣板引擎、UBB 轉 HTML、敏感詞過濾 |
preg_split | 模式分割字串 | array 分割片段 | 多重分隔符、保留分隔符 |
int preg_match ( string $pattern, string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
$pattern:PCRE 模式,需包含定界符(如 /.../)$matches[0]:完整比對內容;$matches[1]...:捕獲組PREG_OFFSET_CAPTURE 旗標可同時取得位置索引<?php
$pattern = '/^1[3-9]\d{9}$/';
$phone = '13800138000';
if (preg_match($pattern, $phone, $m)) {
echo "有效:{$m[0]}";
} else {
echo "格式錯誤";
}
?>
int preg_match_all ( string $pattern, string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )
PREG_PATTERN_ORDER(預設):$matches[0] 完整比對陣列,$matches[1] 第一捕獲組陣列...PREG_SET_ORDER:$matches[0] 第一組所有捕獲,$matches[1] 第二組...<?php
$html = '<img src="a.jpg"><img src="b.png">';
preg_match_all('/<img\s+src="([^"]+)">/i', $html, $m, PREG_SET_ORDER);
foreach ($m as $set) {
echo "完整:{$set[0]}\n圖片:{$set[1]}\n";
}
// 輸出兩組完整標籤與圖片網址
?>
mixed preg_replace ( mixed $pattern, mixed $replacement, mixed $subject [, int $limit = -1 [, int &$count ]] )
$pattern、$replacement 可為陣列,一一對應替換。e 修飾符(已棄用 PHP 7):將替換字串視為 PHP 程式碼執行,現改用 preg_replace_callback。preg_replace_callback($pattern, function($m){...}, $subject) 可動態計算替換內容。$limit 限制替換次數:-1 為無限制。<?php
$pattern = ['/{title}/', '/{author}/', '/{url}/'];
$replace = ['代碼雲', '千手', 'https://codecloud.duapp.com/'];
$str = '標題:{title}<br>作者:{author}<br>地址:{url}';
echo preg_replace($pattern, $replace, $str);
// 標題:代碼雲<br>作者:千手<br>地址:https://codecloud.duapp.com/
?>
<?php
$str = '歡迎來到[url=https://example.com]我的部落格[/url]';
$html = preg_replace_callback(
'/\[url=([^\]]+)\](.*?)\[\/url\]/is',
function($m) {
return '<a href="' . htmlspecialchars($m[1]) . '" target="_blank">' . $m[2] . '</a>';
},
$str
);
echo $html;
// 歡迎來到<a href="https://example.com" target="_blank">我的部落格</a>
?>
array preg_split ( string $pattern, string $subject [, int $limit = -1 [, int $flags = 0 ]] )
PREG_SPLIT_NO_EMPTY:忽略空片段PREG_SPLIT_DELIM_CAPTURE:保留分隔符於結果陣列PREG_SPLIT_OFFSET_CAPTURE:附加位置索引<?php
$str = 'one,two.three#four';
$parts = preg_split('/[,.#]/', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($parts);
// Array ( [0] => one [1] => two [2] => three [3] => four )
?>
| 修飾符 | 說明 |
|---|---|
i | 大小寫不敏感 |
m | 多行模式:^$ 匹配行首尾 |
s | 單行模式:. 匹配換行符 |
x | 擴展模式:忽略空白、允許註解 |
u | UTF-8 模式(處理中文必加) |
U | 非貪婪模式(預設貪婪) |
strpos、str_replace、explode 為 C 實作,速度快數倍。(.*)*、(a+)+ 等模式在長字串會指數級回溯,改用具體字元類別或具備長度限制。/ 時改用 #...#、~...~ 避免大量跳脫。u:否則中文字元會被視為多個位元組導致比對錯誤。preg_match('/\d+/', 'abc') 回傳 0 而非 false?=== 0 或 === false。$matches 為何有時是多維陣列?preg_match_all 預設 PREG_PATTERN_ORDER 產生多維;加 PREG_SET_ORDER 可得更直觀結構。u 修飾符。熟練掌握 preg_* 四大函數與修飾符,能以極少程式碼解決複雜字串處理需求。記住「先考慮非正則替代、再用正則」的原則,並在處理使用者輸入時嚴格驗證模式安全性,避免 ReDoS 攻擊。