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

时间:2014-10-04 21:29:45

标签: javascript regex

我想写一个匹配

的正则表达式
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/

中尝试过

3 个答案:

答案 0 :(得分:4)

匹配

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

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

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

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

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

答案 1 :(得分:2)

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

但是使用前瞻和后引用(explained here)模仿其效果有一个技巧:

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

因此,对于您的a-ba情况,这将成为:

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

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

关键机制是前瞻找到最早,最长可能的子匹配,而后引用阻止引擎中的任何回溯并移动字符串中的位置,因此以下测试{{1}可以执行。

答案 2 :(得分:1)

如果指定起始锚点和结束锚点,则上述正则表达式((a(-b)?)(?!Z))与字符串a-bZ不匹配,请参阅演示here。由于未指定锚点且(-b)是可选的,因此正则表达式引擎首先尝试将a-b匹配,然后在看到以下Z字母时丢弃匹配项。现在,由于可选-b得到匹配,正则表达式引擎回溯。现在它位于aa字母后面没有紧跟Z,因此引擎现在匹配字母a