为什么((a(-b)?)(?!Z))中的a匹配;a-bZ”;

why does ((a(-b)?)(?!Z)) match the a in "a-bZ"?

本文关键字:a-bZ 匹配 为什么 中的      更新时间:2023-09-26

我想写一个与匹配的正则表达式

a
a-b

但前提是这些序列后面没有Z

((a(-b)?)(?!Z))
a       matches a       ok
a-b     matches a-b     ok
aZ      empty           ok
a-bZ    matches a       NOT OK

为什么"a-bZ"与第一个a匹配,尽管(a(-b)周围有一个组?)?我该如何更正?

在javascript RegExp中需要这一点,但这并不重要。试过了http://regexpal.com/

a-bZ匹配,因为(-b)?被忽略,而(?!Z)-符号匹配。

因为(-b)是可选的,所以形式为((a)(?!Z))的每个字符串也会匹配。你可以匹配(a(?!Z))|(a-b(?!Z))

但是,这将与a-bZ匹配(因为a后面跟一个非Z字符)。

如果你想找到所有字符串的实例,例如,a-c不匹配(即使-是非Z字符),你可以这样做:

(a(?![-Z]))|(a-b(?!Z))

您可以使用原子分组使正则表达式工作。遗憾的是,JavaScript正则表达式引擎不支持此功能。

但是有一个技巧可以通过向前看和向后看来模仿它的效果(在这里解释):

(?=(pattern to make atomic))'1

因此,对于a-b或仅a的情况,这将变成:

(?=(a-b|a))'1(?!Z)

注意,需要在组中首先提到较长的子模式a-b,否则它不起作用。

关键机制是先行查找找到最真实、最长的子匹配,而反向引用防止引擎中的任何回溯并移动字符串中的位置,因此可以执行下面的测试(?!Z)

如果指定开始和结束锚点,则上面的正则表达式((a(-b)?)(?!Z))与字符串a-bZ不匹配,请参阅此处的演示。由于未指定锚点,并且(-b)是可选的,正则表达式引擎首先尝试在任何位置匹配a-b,然后在看到以下Z字母时放弃匹配。现在正则表达式引擎会回溯,因为可以选择-b来获得匹配。现在它在a上,字母a后面没有紧跟着Z,所以引擎现在匹配字母a