在PHP正则表达式中使用逻辑运算符AND

7
我想在我的正则表达式中使用逻辑运算符“AND”。我尝试过以下写法:
(?=exp1)(?=exp2)

但在PHP中,?=不能使用,需要用PHP语言编写程序。还有其他方法吗?表达式必须匹配所有条件且顺序任意。

我不想写每个排列组合,例如:

(exp1)(exp2)(exp3)|(exp1)(exp3)(exp2)|....

我认为你需要拆分正则表达式。 - DiogoDoreto
4
PHP支持(?=...),具体请参考:http://php.net/manual/en/regexp.reference.assertions.php。 - Marc B
2个回答

13

PHP 支持前瞻表达式。不过你可能没有正确使用它们。

假设你想匹配包含 foobarbaz 的字符串,你需要使用这个正则表达式:

^(?=.*foo)(?=.*bar)(?=.*baz)

这将返回匹配字符串foobarbazbarbazfoo等的结果。然而,该匹配结果将是空字符串(因为前瞻不消耗任何字符)。如果您想让正则表达式返回字符串本身,请使用

^(?=.*foo)(?=.*bar)(?=.*baz).*

如果满足所有三个条件,那么它将匹配整个字符串。

我会简单地使用

if (preg_match('/^(?=.*foo)(?=.*bar)(?=.*baz)/s', $subject)) {
    # Successful match
} else {
    # Match attempt failed
}

请注意,这个正则表达式也会匹配像 foonly bartender bazooka 这样的字符串。如果不希望匹配这种情况(只允许每个表达式中有一个字符的纯排列),可以使用一个小技巧:

^(?:foo()|bar()|baz()){3}\1\2\3$

匹配的字符串包括foobarbazfoobazbarbarfoobazbarbazfoobazfoobarbazbarfoo(没有其他)。这个“技巧”是受到Jan Goyvaerts和Steven Levithan的优秀书籍“正则表达式菜谱”(第304页)的启发。它的工作原理如下:

  • 每个必需部分(foo等)后面跟着一个空的捕获组(),如果已经匹配了必需部分,则该组始终匹配。
  • 因此,如果所有三个必需部分都匹配,则所有三个空捕获组都会匹配。
  • 以下反向引用仅在每个捕获组参与匹配时成功。
  • 因此,如果字符串为foobarbar,则部分(?:foo()|bar()|baz()){3}将匹配,但\3会失败,因此整个正则表达式也会失败。
  • 但是,如果所有三个必需部分都参与匹配,那么\1\2\3就可以在字符串末尾成功匹配,因为每个捕获组只包含空字符串。

@tim,你能提供关于这个的资源或补充说明吗?我以前从未见过像foo()|bar()|baz()这样的东西。 - bozdoz
我想问的是,空括号的意义是什么? - bozdoz
@bozdoz:我添加了一份解释和参考资料。 - Tim Pietzcker

1
除了@Tim的回答之外:
(?=exp1)(?=exp2)

这是不可能的。你用简单的英语说:确保此处跟随的文本是exp1,并确保此处跟随的文本是exp2。这绝对不可能成立。它永远不会匹配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接