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

PHP preg_match 正則表達式函數完整實戰指南

     編輯:PHP 相關知識

PHP preg_match 正則表達式函數完整實戰指南

preg_match() 是 PHP 執行 **PCRE (Perl 相容正則表達式)** 匹配的核心函數,僅返回首次匹配結果。本文系統整理語法、參數、修飾符、常用模式、效能優化與實戰陷阱。

函數原型

preg_match(
    string $pattern,      // 正則模式 (含定界符)
    string $subject,      // 目標字串
    array &$matches = null, // 匹配結果引用
    int $flags = 0,       // 標記
    int $offset = 0       // 起始偏移量
): int|false

返回值

  • 1:匹配成功
  • 0:匹配失敗
  • false:錯誤 (如模式編譯失敗)

$matches 結構詳解

$str = 'Email: test@example.com, Phone: 138-0000-1111';
preg_match('/([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})/i', $str, $m);

print_r($m);
/*
Array
(
    [0] => test@example.com      // 整個模式匹配內容
    [1] => test@example.com      // 第 1 個捕獲組
)
*/
  • $matches[0]:完整匹配
  • $matches[1]...$matches[n]:第 n 個捕獲組 (...)
  • 命名捕獲組 (?P...) 同時生成數字鍵與字串鍵

常用修飾符 (Pattern Modifiers)

修飾符名稱效果
iPCRE_CASELESS大小寫不敏感
mPCRE_MULTILINE^$ 匹配行首尾而非字串首尾
sPCRE_DOTALL. 匹配換行符
uPCRE_UTF8**UTF-8 模式 (中文必加)**,正確處理多位元組字元
xPCRE_EXTENDED忽略模式空白/註釋,可寫多行可讀模式
APCRE_ANCHORED強制從字串開頭匹配 (等價 ^)
DPCRE_DOLLAR_ENDONLY$ 僅匹配字串結尾,不匹配末尾換行前
UPCRE_UNGREEDY反轉貪婪/非貪婪量詞預設行為
JPCRE_DUPNAMES允許重複命名捕獲組

實戰範例庫

1. 提取首個 URL

$text = '訪問 https://example.com/path?query=1 或 https://test.org';
preg_match('/https?:\/\/[^\s<>"\']+/i', $text, $m);
// $m[0] = 'https://example.com/path?query=1'

2. 驗證手機號 (中國大陸)

function isMobile(string $phone): bool {
    return preg_match('/^1[3-9]\d{9}$/', $phone) === 1;
}

3. 提取 HTML 標籤屬性

$html = '頭像';
preg_match('/]*src\s*=\s*["\']([^"\']+)["\']/i', $html, $m);
// $m[1] = 'avatar.jpg'

4. 解析日期 (YYYY-MM-DD)

$dateStr = '出生日期:1990-05-12';
preg_match('/(\d{4})-(\d{2})-(\d{2})/', $dateStr, $m);
// $m = ['1990-05-12', '1990', '05', '12']

5. 命名捕獲組提取鍵值對

$log = 'user=john action=login ip=192.168.1.1';
preg_match('/(?P\w+)\s+(?P\w+)\s+(?P[\d.]+)/', $log, $m);
/*
$m = [
    0 => 'user=john action=login ip=192.168.1.1',
    'user' => 'john', 1 => 'john',
    'action' => 'login', 2 => 'login',
    'ip' => '192.168.1.1', 3 => '192.168.1.1'
]
*/

6. UTF-8 中文處理 (必加 u 修飾符)

$text = '你好世界 Hello';
preg_match('/[\p{Han}]+/u', $text, $m);  // \p{Han} 匹配漢字
// $m[0] = '你好世界'

preg_match('/^\p{L}+$/u', '你好');  // 純字母(含中文) -> 1
preg_match('/^\w+$/', '你好');       // 無 u 修飾符 -> 0 (\w 不匹配中文)

旗標參數 ($flags)

常數說明
PREG_OFFSET_CAPTURE結果包含偏移量 [匹配內容, 偏移量]
PREG_UNMATCHED_AS_NULL未匹配的捕獲組設為 null 而非空字串 (PHP 7.2+)
preg_match('/(\d+)-(\d+)/', 'abc-123', $m, PREG_OFFSET_CAPTURE);
/*
$m = [
    0 => ['123', 4],
    1 => ['123', 4],
    2 => [null, -1]  // 第二組未匹配
]
*/

效能優化鐵律

  1. 錨點優先:^pattern 或 pattern$ 減少回溯
  2. 具體化字元類:[a-z] 優於 .,\d 優於 [0-9]
  3. 避免嵌套量詞:(a+)* 導致災難性回溯
  4. 使用非捕獲組:(?:...) 不需捕獲時節省記憶體
  5. 預編譯重用:長期運行進程 (Swoole/Workerman) 中將模式編譯為靜態變數
  6. 避免過度正則:簡單字串操作用 strpos/substr/explode,快 10-100 倍

常見陷阱與避坑

陷阱錯誤代碼正確代碼原因
定界符缺失preg_match('/pattern', $s)preg_match('/pattern/', $s)模式必須被定界符包圍
定界符衝突preg_match('/https:///', $s)preg_match('~https://~', $s)改用 ~ # @ 等不衝突定界符
中文亂碼/匹配失敗preg_match('/\w+/', '中文')preg_match('/\w+/u', '中文')**必須加 u 修飾符** 啟用 UTF-8
貪婪匹配過度preg_match('/
.*<\/div>/', $html)
preg_match('/
.*?<\/div>/', $html)
改用非貪婪 *? 或 [^<]*
轉義遺漏preg_match('/file.php/', $s)preg_match('/file\.php/', $s). 需轉義為 \.
位元組偏移 vs 字元偏移$offset 按字元計算配合 u 修飾符,offset 為字元位置無 u 時 offset 為位元組

preg_match vs preg_match_all vs preg_replace

函數用途返回典型場景
preg_match首次匹配0/1/false驗證、提取第一個、條件判斷
preg_match_all全局匹配匹配次數提取所有郵箱、分詞、日誌解析
preg_replace搜尋替換新字串/次數關鍵字高亮、模板渲染、清洗
preg_replace_callback回調替換新字串複雜替換邏輯 (如 BBCode 解析)
preg_split正則分割陣列分割複雜分隔符、保留分隔符
preg_quote轉義正則元字元字串動態構建模式時保護用戶輸入

進階:PCRE JIT (PHP 7.0+)

// php.ini
pcre.jit=1  ; 預設開啟

// 運行時檢查
var_dump(pcre_jit_support());  // bool(true)

// 複雜模式受益最大,簡單模式 JIT 開銷可能超過收益
// 可通過 ini_set('pcre.jit', '0') 關閉

掌握 preg_match 核心在於:**正確的模式構建 + u 修飾符處理 UTF-8 + 理解貪婪/非貪婪 + 善用命名捕獲組**。複雜解析任務優先考慮專用解析器 (HTML 用 DOMDocument、JSON 用 json_decode、URL 用 parse_url),正則作為輔助工具而非萬能鑰匙。

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