1

我的问题与这个问题非常相似,只是我想让每个交替都是可选的,并且不重复。

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

XAB
XBA
XA
XB
X

它不能匹配 XAA、XBB、XABA、XABB、XBAA

这是我到目前为止所拥有的:

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

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

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

4

3 回答 3

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]+bruleswith [A-Z]+

在线演示

于 2013-12-22T22:05:42.060 回答
1

使用否定的前瞻断言

/(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
于 2013-12-22T22:05:56.043 回答
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”)

于 2013-12-22T23:17:30.417 回答