正则表达式:以任何顺序匹配可选的替换,不允许重复

时间:2013-12-22 21:50:30

标签: php regex alternating

我的问题与this非常相似,只是我想让每个轮换都是可选的,而且是非重复的。

示例:正则表达式需要匹配以下字符串(这是过于简单的,A和B可能很复杂):

XAB
XBA
XA
XB
X

它无法匹配XAA,XBB,XABA,XABB,XBAA

这是我到目前为止所做的:

/(X)(?:(A)|(B)){0,2}$/

这允许重复(例如XAA),并且似乎在PHP中使用空数组元素导致XB出现问题。

编辑:忘记提到我需要获取X,A和B的实际值(如果可用)。它不仅仅是完整字符串的匹配。

3 个答案:

答案 0 :(得分:1)

最干净的方法是定义每个组,然后按特定顺序使用这些定义:

# Start defining
(?(DEFINE)
   (?<X>xrules)
   (?<A>arules)
   (?<B>brules)
)
# End defining
^                    # begin of string
(?&X)                # Use rule X
   (?:               # non-capturing group
      (?&A)(?&B)?    # Use rule A and make rule B optional
   |                 # or
      (?&B)(?&A)?    # Use rule B and make rule A optional
   )?                # make it optional
$                    # end of string

当然,您可以使用xrules[a-z]+brules等有效正则结构更改[A-Z]+

Online demo

答案 1 :(得分:1)

使用negative lookahead assertions

/(X)(?!A{2})(?!B{2})(?:(A)|(B)){0,2}$/

<强>说明:

(X)       # Match and capture X
(?!A{2})  # Assert that it's impossible to match AA
(?!B{2})  # Same for BB
(?:       # Non-capturing group:
 (A)      # Match and capture A
|         # or
 (B)      # Match and capture B
){0,2}    # Do this 0-2 times
$         # Then match the end of the string

答案 2 :(得分:0)

您的问题可以有以下标题:“如何不重复可选组?”。

$pattern = <<<'LOD'
~
    (?(DEFINE)
        (?<X> FOO )
        (?<A> BAR )
        (?<B> BAZ )
    )

^   \g<X> (?: \g<A> (?! .* \g<A> ) | \g<B> (?! .* \g<B> ) ){0,2}   $
~xs
LOD;

\g<A> (?! .* \g<A> )迫使A组在字符串中只出现一次,因为前瞻性为负(即:“后面没有任何东西和A组”)