Regex 如果第一个X中有一个X,第二个Y可以是0,则匹配
我目前正在做一个项目。我需要一个正则表达式,它取Y和X,并且X对之间用Y分隔。它不必是相等的数字,但不能包含多个X'e 示例:Regex 如果第一个X中有一个X,第二个Y可以是0,则匹配,regex,Regex,我目前正在做一个项目。我需要一个正则表达式,它取Y和X,并且X对之间用Y分隔。它不必是相等的数字,但不能包含多个X'e 示例: # Don't match: XXXYYYYY #Match: XYXYYYY X 我迄今为止的努力: {Y*[X |^X]Y*[X |^X]Y*}* 问题是,如果第一个和第二个分别有X和X,Y仍然可以是0。我可以直接测试双X吗 它有什么不寻常之处 ^(?:X(?!X)|Y)+$ 说明:这只是一系列的X和Y,其中一个X后面不能跟另一个X(负向前看)。它有什么不寻
# Don't match:
XXXYYYYY
#Match:
XYXYYYY
X
我迄今为止的努力:
{Y*[X |^X]Y*[X |^X]Y*}*
问题是,如果第一个和第二个分别有X和X,Y仍然可以是0。我可以直接测试双X吗 它有什么不寻常之处
^(?:X(?!X)|Y)+$
说明:这只是一系列的X和Y,其中一个X后面不能跟另一个X(负向前看)。它有什么不寻常之处
^(?:X(?!X)|Y)+$
说明:这只是一系列的X和Y,其中一个X不能后跟另一个X(负前瞻)
试试这个。这应该可以满足您的要求。请参阅演示
试试这个。这应该可以满足您的要求。请参阅演示
您可以使用此模式:
^Y*(XY+)*X?$
如果要确保至少有一个字符,可以单独检查长度或在开头添加前瞻:
^(?=.)Y*(?:XY+)*X?$
关于灾难性回溯:
如果使用DFA正则表达式引擎,则不会出现问题,因为没有回溯
如果使用NFA正则表达式引擎,可以通过以下几种方法防止灾难性回溯:
^Y*(XY|Y)*X?$ # possible but not really efficient
^Y*(?>XY+)*X?$ # using an atomic group (if available)
^Y*(?:XY+)*+X?$ # using a possessive quantifier (if available)
^Y*(?=((XY+)*))\1X?$ # emulate `(?>(?:XY+)*)`
^Y*(?:(?=(XY+))\1)*X?$ # emulate `(?>XY+)*`
您可以使用以下模式:
^Y*(XY+)*X?$
如果要确保至少有一个字符,可以单独检查长度或在开头添加前瞻:
^(?=.)Y*(?:XY+)*X?$
关于灾难性回溯:
如果使用DFA正则表达式引擎,则不会出现问题,因为没有回溯
如果使用NFA正则表达式引擎,可以通过以下几种方法防止灾难性回溯:
^Y*(XY|Y)*X?$ # possible but not really efficient
^Y*(?>XY+)*X?$ # using an atomic group (if available)
^Y*(?:XY+)*+X?$ # using a possessive quantifier (if available)
^Y*(?=((XY+)*))\1X?$ # emulate `(?>(?:XY+)*)`
^Y*(?:(?=(XY+))\1)*X?$ # emulate `(?>XY+)*`
因为上面的答案使用了前瞻性,所以这个答案提供了一个普通正则表达式的解决方案:
^(X?Y)*X?$
上述解决方案假定允许使用空字符串。否则:
^((X?Y)+X?|X)$
(请随意将组设置为非捕获)
多亏了单面体的简化XY | Y
到X?Y
如果还有人对这个答案的正确性有疑问: DFA可从上述方程式中得出
如果不允许使用空字符串,请删除
R1
中的+λ
。由于上述答案使用了前瞻性,此答案提供了一个普通正则表达式的解决方案:
^(X?Y)*X?$
上述解决方案假定允许使用空字符串。否则:
^((X?Y)+X?|X)$
(请随意将组设置为非捕获)
多亏了单面体的简化XY | Y
到X?Y
如果还有人对这个答案的正确性有疑问: DFA可从上述方程式中得出
如果不允许使用空字符串,请删除
R1
中的+λ
。@almasshaikh已经更新了问题:为什么不直接测试XX
,发现时拒绝?@单面体不是重点,请您对此作出反应,抱歉,但我需要的只是一些理论,也许我可以测试双X或类似的东西你在找什么样的RE?style regex,或style ERE,或@almasshaikh重复使用的平原更新了问题:为什么不直接测试XX
并在发现时拒绝?@单面体这不是重点,请您对此作出反应,抱歉,但我需要的只是一些理论,也许我可以测试双X或类似的东西你在找什么样的RE?由于Y
在逻辑上看起来等于或大于X
s的数量,因此将替换项更改为在前面包含Y
,可能会使其在匹配输入时稍微更有效。@Unihedron您甚至可以做得更好:^(?:Y++|X(?!X))+$
或^(?:(?>Y+)| X(?!X))+$
但由于OP没有指定正则表达式的风格,我省略了优化。有见地的评论和很棒的观点!然而值得注意的是,在PCRE中,Y++
被定义为与(?>Y+
)相同。是的,但例如,所有格量词修饰符(++
)在.NET中不可用,因此您必须使用原子组((?>)
)。。。同样,一切都取决于味道:)因为Y
在逻辑上看起来等于或大于X
s的数量,所以将替换项更改为在前面包含Y
,可能会使其在匹配输入时稍微更有效。@Unihedron您甚至可以做得更好:^(?:Y++;X(?!X))++$
或^((?>Y+)|X(?!X))+$
但是由于OP没有指定正则表达式的风格,我没有进行优化。有见地的评论和很棒的观点!然而值得注意的是,在PCRE中,Y++
被定义为与(?>Y+
)相同。是的,但例如,所有格量词修饰符(++
)在.NET中不可用,因此您必须使用原子组((?>)
)。。。同样,一切都取决于味道:)有趣的理论,尽管为了避免灾难性的回溯烧掉用户的代码,最好使用(?>)
而不是(?:)
语言支持的:)^Y*(XY | Y)*X?$
删除第一个Y*
(因为(XY | Y)*
已经包含在(XY | Y)*
中,解决方案将与我的相同。其余部分是多余的,因为^(XY | Y)*X?$
永远不会有回溯问题。@nhahdh:^Y*(XY | Y)*X?$
确实可以缩短为^(X?Y)*X?$
。但是,此模式的效率较低,因为失败前的步数比使用原子分组的模式大4倍。因此,它们一点都不冗余。因此,通过单面体简化,最有效的模式是^(?>X?Y+)*+X?$
@casimirithippolyte:我无法观察到4x的差异。但是,如果我使用^(X?Y)*+X?$
,我确实看到了2x的差异。(?>
在可能的情况下是不必要的