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

PHP 正則表達式捕獲組與非捕獲組深度解析:命名、反向引用與前瞻後顧

     編輯:PHP 相關知識

PHP 正則捕獲組完全指南:從基礎編號到進階零寬斷言

正則表達式的捕獲組是擷取、替換、驗證字串的核心機制。PHP 採用 PCRE 庫,完整支援編號捕獲組、命名捕獲組、非捕獲組、反向引用、前瞻後顧等進階功能。本文系統性講解各類捕獲組語法、行為差異與實戰應用。

捕獲組基礎:編號與 $matches 陣列

$pattern = '/a=(\d+)b=(\d+)c=(\d+)/';
$str = 'a=4b=98c=56';
preg_match($pattern, $str, $matches);

print_r($matches);
/*
Array
(
    [0] => a=4b=98c=56     // 完整匹配(編號 0)
    [1] => 4               // 第 1 個捕獲組
    [2] => 98              // 第 2 個捕獲組
    [3] => 56              // 第 3 個捕獲組
)
*/

編號規則:由左至右按左括號 ( 出現順序編號,從 1 開始。巢狀括號同樣遵循此規則。

非捕獲組:(?:...)

$pattern = '/a=(\d+)b=(?:\d+)c=(\d+)/'; // 第 2 組不捕獲
preg_match($pattern, 'a=4b=98c=56', $matches);
/*
Array
(
    [0] => a=4b=98c=56
    [1] => 4
    [2] => 56              // 原第 3 組變為第 2 組
)
*/

用途:分組套用量詞(如 (?:abc)+)、邏輯分組但不佔用編號、提升效能(略過捕獲儲存)。

命名捕獲組:(?...)、(?'name'...)、(?P...)

$pattern = '/a=(\d+)b=(?\d+)c=(\d+)/';
preg_match($pattern, 'a=4b=98c=56', $matches);
/*
Array
(
    [0] => a=4b=98c=56
    [1] => 4
    [sec] => 98            // 命名鍵值
    [2] => 98              // 同時保留編號
    [3] => 56
)
*/

優點:程式碼可讀性高、不受組別順序變動影響、支援 $matches['name'] 直接存取。

反向引用:\n、\k、\g{n}

// 匹配重複單詞
$pattern = '/\b(\w+)\s+\1\b/';
preg_match($pattern, 'hello hello world'); // 匹配 "hello hello"

// 替換時使用反向引用
$pattern = '/(\d{4})-(\d{2})-(\d{2})/';
$replacement = '$3/$2/$1'; // 或 \\3/\\2/\\1
echo preg_replace($pattern, $replacement, '2024-01-15'); // 15/01/2024

// 命名反向引用(PHP 7+)
$pattern = '/(?\d{4})-(?\d{2})-(?\d{2})/';
$replacement = '${day}/${month}/${year}';

零寬斷言(非捕獲組特殊形式)

語法名稱含義範例匹配
(?=...)正向前瞻後面必須是...\d(?=px) 匹配 "12px" 中的 "12"
(?!...)負向前瞻後面不能是...\d(?!px) 匹配 "12em" 中的 "12"
(?<=...)正向後顧前面必須是...(?<=\$)\d+ 匹配 "$100" 中的 "100"
(?負向後顧前面不能是...(?
// 正向前瞻:匹配後面跟著 abc 的數字
preg_match('/\d(?=abc)/', 'ab36abc8eg', $m); // $m[0] = "6"

// 正向後顧:匹配前面是 abc 的數字
preg_match('/(?<=abc)\d/', 'ab36abc8eg', $m); // $m[0] = "8"

// 實戰:千分位分隔符(不匹配小數點後)
$number = '1234567.89';
echo preg_replace('/(?<=\d)(?=(\d{3})+(?!\d))/', ',', $number); // 1,234,567.89

實戰綜合範例:解析 URL 參數

$url = 'https://example.com/path?id=123&name=test&tag=php%20regex';

$pattern = '/[?&](?[^=&]+)=(?[^&]*)/';
preg_match_all($pattern, $url, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    echo "{$match['key']} = " . urldecode($match['value']) . "\n";
}
/*
id = 123
name = test
tag = php regex
*/

效能與最佳實踐建議

  • 優先使用非捕獲組 (?:...) 除非需要捕獲內容
  • 複雜正則使用命名捕獲組提升維護性
  • 避免過度巢狀與過多捕獲組(PCRE 限制 65535 組)
  • 固定字串前綴優於 ^.* 開頭
  • 使用 preg_match_all() 批次處理優於迴圈 preg_match()

深入掌握捕獲組機制,能編寫高效、可維護的正則表達式,解決複雜字串解析與轉換需求。

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