PHP Conference Japan 2024

条件子模式

可以使匹配过程有条件地遵循子模式,或者根据断言的结果或先前的捕获子模式是否匹配来选择两个备选子模式之一。条件子模式的两种可能形式是

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

如果条件满足,则使用 yes-pattern;否则(如果存在)使用 no-pattern。如果子模式中有多于两个备选方案,则会发生编译时错误。

有两种条件。如果括号之间的文本包含一系列数字,则如果该数字的捕获子模式先前已匹配,则条件满足。考虑以下模式,其中包含非显著空格以使其更易读(假设使用了PCRE_EXTENDED选项)并将其分为三个部分以便于讨论

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

第一部分匹配一个可选的开括号,如果存在该字符,则将其设置为第一个捕获的子字符串。第二部分匹配一个或多个不是括号的字符。第三部分是一个条件子模式,测试第一组括号是否匹配。如果它们匹配,也就是说,如果主题以开括号开头,则条件为true,因此执行 yes-pattern 并需要一个闭括号。否则,由于 no-pattern 不存在,因此子模式不匹配任何内容。换句话说,此模式匹配一系列非括号,可以选择用括号括起来。

如果条件是字符串(R),则在对模式或子模式进行递归调用时,条件满足。在“顶层”,条件为假。

如果条件不是一系列数字或 (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