2024 年 PHP Conference Japan

條件式子模式

可以根據斷言的結果,或者先前的捕獲子模式是否匹配,來使匹配過程有條件地遵循子模式或在兩個替代子模式之間進行選擇。條件式子模式的兩種可能形式為

(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)

如果條件滿足,則使用 yes-pattern;否則使用 no-pattern(如果存在)。如果子模式中有多於兩個替代方案,則會發生編譯時錯誤。

條件式子模式有兩種。如果括號內的文字是由一串數字組成,則當該數字所對應的子模式先前已匹配成功時,條件成立。考慮以下模式,其中包含為了提高可讀性而添加的無意義空白(假設使用了 PCRE_EXTENDED 選項),並為了便於討論將其分為三個部分:

( \( )? [^()]+ (?(1) \) )

第一部分匹配一個可選的左括號,如果該字元存在,則將其設為第一個捕獲的子字串。第二部分匹配一個或多個非括號字元。第三部分是一個條件式子模式,用於測試第一組括號是否匹配成功。如果匹配成功,也就是說,如果目標字串以左括號開頭,則條件為true,因此會執行「yes-pattern」並要求匹配一個右括號。否則,由於沒有「no-pattern」,子模式將不匹配任何內容。換句話說,此模式匹配一個非括號字元序列,該序列可選擇性地用括號括起來。

如果條件是字串 (R),則在已遞迴呼叫該模式或子模式時,條件成立。在「頂層」,條件為 false。

如果條件不是一串數字或 (R),則它必須是一個斷言。這可以是肯定或否定預查或回查斷言。考慮以下模式,同樣包含無意義空白,並且在第二行有兩個替代方案:

(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )

條件是一個肯定預查斷言,匹配一個可選的非字母序列,後跟一個字母。換句話說,它測試目標字串中是否存在至少一個字母。如果找到字母,則目標字串會與第一個替代方案匹配;否則,它會與第二個替代方案匹配。此模式匹配 dd-aaa-dd 或 dd-dd-dd 形式的字串,其中 aaa 是字母,dd 是數字。

新增註解

使用者貢獻的註解 1 則註解

匿名
13 年前
重複子模式會重複其中包含的條件式,並在每次迭代時更新子模式匹配。

考慮以下程式碼,它掃描 HTML 並追蹤角括號「<」和「>」。如果匹配到左括號「<」,則在重複可能結束之前必須接著匹配右括號「>」。這樣,正規表示式將只會有效地匹配標籤以外的內容。

<?php
$pattern
='%(*ANY)(.*?(<)(?(2).*?>)(.*?))*?\'\'%s';
$replace='\1Fred';
$subject=
'<html><body class=\'\'>\'\' went to '\'\meyer and ran
into <b>\'\'</b>.
</body></html>'
echo preg_replace("%(*ANY)(.*?((<)(?(3).*?>).*?)*?)\'\'%s",'\1Fred',$subject);
?>

輸出將是
'<html><body class=\'\'>Fred went to Fredmeyer and ran
into <b>Fred</b>.
</body></html>'
To Top