正則表達式的強大在於「選擇」、「分組」與「引用」三大機制的組合運用。本文深入解析分支結構 `|`、捕獲分組 `()`、非捕獲分組 `(?:)`、前瞻斷言 `(?=)`/`(?!)`、後向引用 `\1` 等核心概念,並通過實戰案例展示其應用場景。
匹配多個備選模式之一,優先級最低,左右嘗試匹配。
/cat|dog|bird/ # 匹配 cat 或 dog 或 bird
/^Chapter|Section [1-9][0-9]?$/ # 錯誤!實際匹配:行首 Chapter 或 行尾 Section 12
/^(Chapter|Section) [1-9][0-9]?$/ # 正確:分組限制選擇範圍
| 語法 | 名稱 | 捕獲 | 用途 |
|---|---|---|---|
(pattern) | 捕獲分組 | 是 | 提取子串、後向引用、替換引用 $1 |
(?:pattern) | 非捕獲分組 | 否 | 僅分組不捕獲,提升性能 |
(?<name>pattern) | 命名捕獲組 | 是 | PHP/PCRE 支援,\k<name> 或 $matches['name'] 引用 |
(?=pattern) | 正向前瞻 | 否 | 斷言後方匹配,不消耗字符 |
(?!pattern) | 負向前瞻 | 否 | 斷言後方不匹配 |
(?<=pattern) | 正向後顧 | 否 | 斷言前方匹配 (固定寬度) |
(?<!pattern) | 負向後顧 | 否 | 斷言前方不匹配 |
<?php
$text = "Windows 3.1, Windows 95, Windows 98, Windows NT, Windows 2000";
// 僅匹配 95/98/NT/2000 後的 Windows
$pattern = '/Windows(?= 95| 98| NT| 2000)/';
preg_match_all($pattern, $text, $matches);
// $matches[0] = ['Windows', 'Windows', 'Windows', 'Windows']
// 替換為 Windows 11
$new_text = preg_replace('/Windows(?= 95| 98| NT| 2000)/', 'Windows 11', $text);
// 結果: "Windows 3.1, Windows 11, Windows 11, Windows 11, Windows 11"
<?php
$text = "Is is the cost of of gasoline going up up?";
// \b 邊界,([a-z]+) 捕獲單詞,\1 後向引用
$pattern = '/\b([a-z]+)\s+\1\b/i';
$clean = preg_replace($pattern, '$1', $text);
// 結果: "Is the cost of gasoline going up?"
// 進階:檢測跨行重複
$pattern_m = '/\b([a-z]+)\s+\1\b/im';
<?php
$uri = "https://api.example.com:8443/v1/users/profile";
$pattern = '/^(\w+):\/\/([^:\/]+)(?::(\d+))?(.\*)?$/';
if (preg_match($pattern, $uri, $m)) {
// $m[0] 完整匹配
// $m[1] 協議: https
// $m[2] 域名: api.example.com
// $m[3] 端口: 8443 (可選)
// $m[4] 路徑: /v1/users/profile
print_r($m);
}
/*
Array
(
[0] => https://api.example.com:8443/v1/users/profile
[1] => https
[2] => api.example.com
[3] => 8443
[4] => /v1/users/profile
)
*/
<?php
$html = '<img src="avatar.png" alt="用戶頭像" class="img-rounded" data-id="123" />';
// 提取所有屬性名值對
preg_match_all('/(\w+)\s*=\s*"([^"]*)"/', $html, $m, PREG_SET_ORDER);
foreach ($m as $match) {
echo "屬性: {$match[1]} = {$match[2]}\n";
}
/*
屬性: src = avatar.png
屬性: alt = 用戶頭像
屬性: class = img-rounded
屬性: data-id = 123
*/
$text = "A1 B22 C333";
$pattern = '/([A-Z])(\d+)/';
// PREG_SET_ORDER: 結果按匹配分組
preg_match_all($pattern, $text, $m, PREG_SET_ORDER);
/*
$m[0] = ['A1', 'A', '1']
$m[1] = ['B22', 'B', '22']
$m[2] = ['C333', 'C', '333']
*/
// PREG_OFFSET_CAPTURE: 返回位移
preg_match_all($pattern, $text, $m, PREG_OFFSET_CAPTURE);
/*
$m[0][0] = ['A', 0]
$m[1][0] = ['1', 1]
$m[0][1] = ['B', 3]
...
*/
掌握「選擇→分組→引用」鏈路,是編寫高效、可維護正則的關鍵。記住:只捕獲你需要的,斷言不消耗字符,後向引用威力巨大但慎用嵌套。