条件子模式(Conditional subpatterns)
正则表达式允许在模式中根据不同的条件使用不同的匹配子模式。也就是条件子模式(Conditional subpatterns)。它的格式如下:(?(condition)yes-pattern)或者 (?(condition)yes-pattern|no-pattern)。如果条件满足,采用yes-pattern,否则,采用no-pattern(如果在模式中提供了话)。
条件子模式中的条件有两种,一种是断言结果,另一种是看是否捕获一个前面提供的子模式。
如果在表示条件的圆括号里的内容是一个数字,它表示当此数字代表的子模式被成功匹配时条件为真。看看下面这个例子,/( \( )? [^()]+ (?(1) \) )/x,(注意“x”模式修正符表示忽略字符类外的空白字符和#符号之后的内容)。
这个模式的第一部分“( \( )?”匹配了一个可选的左图括号“(”,第二部分“[^()]+”匹配了一个以上的非圆括号字符,最后一部分“(?(1) \) )”是个条件子模式,表示如果捕获到\1也即那个可选的左圆括号,第三部分应该会出现一个右圆括号“)”。
如果在表示条件的圆括号内是一个“R”字符,表示在这个模式或子模式被递归调用时条件为真,在递归调用的顶层,这个条件为假。关于正则表达式中的递归,我们会在后面的部分专题介绍。
如果条件不是一个数字或R字符,则它必需是一个断言。断言可以是肯定或否定的前身或后向断言。让我们看下面这个例子。
/(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )/x
为了让这个正则表达式更容易阅读,我们特意采用了x模式修正符,这样我们可以在用模式中加入空格对符式进行格式上的分隔并分行表示而不影响模式的解析。
第一行的条件子模式使用了一个肯定的前向断言,表示一串可选的非小写字母后面跟随着一个小写字母。换句话说,它查看目标字符串是否至少包含一个小写字母,如果是,它用“|”前的模式对目标进行匹配,看目标是否为看目标是否为两个数字-三个小写字母-两个数字这种格式,否则,用“|”来匹配目标,看目标字符串是否为由“-”分隔的三段二位十进制数字。
正则表达式中的注释
为了让正则表达式更容易阅读,可以在其中加入注释语句。通常注释由左圆括号和井号——“(#“开始,当遇到下一个右圆括号”)“结束。注释是禁止嵌套的。
如果设定了“x”模式修正符,任何字符类之外(也即[]之外)的井号(#)和下一个新行标记之间的部分也被作为注释看待。