我的问题与this非常相似,只是我想让每个轮换都是可选的,而且是非重复的。
示例:正则表达式需要匹配以下字符串(这是过于简单的,A和B可能很复杂):
XAB
XBA
XA
XB
X
它无法匹配XAA,XBB,XABA,XABB,XBAA
这是我到目前为止所做的:
/(X)(?:(A)|(B)){0,2}$/
这允许重复(例如XAA),并且似乎在PHP中使用空数组元素导致XB出现问题。
编辑:忘记提到我需要获取X,A和B的实际值(如果可用)。它不仅仅是完整字符串的匹配。答案 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]+
。
答案 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组”)