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

正則表達式限定符與定位符:精確控制匹配次數與位置

     編輯:PHP 綜合知識

限定符決定「匹配多少次」,定位符決定「在哪裡匹配」。二者結合,能精準描述字符串模式。本文系統講解貪婪/惰性/佔有優先三種匹配模式、各類限定符語法、邊界定位符,並以 HTML 標籤匹配為例演示貪婪與惰性的關鍵差異。

限定符完整對照表

語法名稱匹配次數等價寫法貪婪性
*零或多次0~∞{0,}貪婪
+一次或多次1~∞{1,}貪婪
?零或一次0~1{0,1}貪婪
{n}固定 n 次n-貪婪
{n,}至少 n 次n~∞-貪婪
{n,m}n 到 m 次n~m-貪婪
*?零或多次 (惰性)0~∞{0,}?惰性
+?一次或多次 (惰性)1~∞{1,}?惰性
??零或一次 (惰性)0~1{0,1}?惰性
{n,m}?n 到 m 次 (惰性)n~m-惰性

章節編號匹配實例

<?php
// 匹配 "Chapter 1" 到 "Chapter 999"
$patterns = [
    '/Chapter [1-9][0-9]*/'     => '任意位數 (貪婪)',
    '/Chapter [0-9]{1,3}/'      => '1-3 位數字 (含 0 開頭)',
    '/Chapter [1-9][0-9]{0,2}/' => '1-3 位,不以 0 開頭 (推薦)',
    '/Chapter [1-9][0-9]?/'     => '1-2 位,不以 0 開頭',
];

$test = "Chapter 1\nChapter 12\nChapter 123\nChapter 05\nChapter 0";
foreach ($patterns as $pat => $desc) {
    echo "$desc: $pat\n";
    preg_match_all($pat, $test, $m);
    print_r($m[0]);
    echo "\n";
}

貪婪 vs 惰性:HTML 標籤匹配經典案例

<?php
$html = '<H1>Chapter 1 – Introduction</H1><P>Content</P>';

// 貪婪模式:匹配盡可能多
$greedy = '/<.*>/';
preg_match($greedy, $html, $m);
echo "貪婪: {$m[0]}\n";
// 輸出: <H1>Chapter 1 – Introduction</H1><P>Content</P>

// 惰性模式:匹配盡可能少
$lazy = '/<.*?>/';
preg_match($lazy, $html, $m);
echo "惰性: {$m[0]}\n";
// 輸出: <H1>

// 佔有優先模式 (PHP/PCRE 不直接支援,需用原子組)
$possessive = '/<.*+>/'; // 錯誤語法
// 正確寫法:原子組 (?>.*)
$atomic = '/<(?>.)*>/'; // 實際不常用

匹配機制對比

模式行為回溯適用場景
貪婪先匹配最長,失敗時回溯是大多數情況,性能較好
惰性先匹配最短,成功時擴展是分隔符匹配、標籤內容提取
佔有優先匹配最長,不回溯否避免災難性回溯,需原子組支援

定位符(錨點)

符號含義多行模式 (m) 影響
^字符串開始 / 行首啟用後匹配每行開頭
$字符串結束 / 行尾啟用後匹配每行結尾
\A絕對字符串開始不受 m 影響
\Z絕對字符串結束 (或末尾換行前)不受 m 影響
\z絕對字符串結束不受 m 影響
\b單詞邊界-
\B非單詞邊界-
\G上次匹配結束位置配合 \G 連續掃描

實戰:提取 HTML 標籤內容

<?php
$html = '<div class="box"><p>Hello</p><span>World</span></div>';

// 1. 提取第一個 div 完整內容 (惰性)
preg_match('/<div[^>]*>(.*?)<\/div>/is', $html, $m);
echo "內容: {$m[1]}\n";
// 輸出: <p>Hello</p><span>World</span>

// 2. 提取所有 p 標籤文本
preg_match_all('/<p>(.*?)<\/p>/is', $html, $m);
print_r($m[1]);
// Array ( [0] => Hello )

// 3. 驗證完整 HTML 結構 (簡易)
$valid = '/^<(\w+)[^>]*>.*?<\/\1>$/s'; // \1 後向引用標籤名

常見錯誤與避坑

  1. .* 匹配換行需加 s 修飾符 (PCRE_DOTALL)
  2. {n,m} 中間不能有空格:{1, 3} 錯誤
  3. 惰性量詞 `*?` 在某些引擎中可能比貪婪慢(需更多擴展嘗試)
  4. 邊界 `\b` 依賴 `\w` 定義(字母數字下劃線),中文邊界需用 Unicode 屬性 `\p{Han}`

總結

限定符控制數量,定位符控制位置。貪婪是默認、惰性按需、佔有優先防回溯。實戰中:能用具體字符類別不用點號,能用錨點定位不用模糊匹配,能用惰性分隔符不用貪婪跨界。

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