Javascript 为什么((a(-b))(?!Z))与“中的a”匹配;“a-bZ”吗;?
我想写一个匹配的正则表达式Javascript 为什么((a(-b))(?!Z))与“中的a”匹配;“a-bZ”吗;?,javascript,regex,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(-b)周围有一群人,为什么“a-bZ”与第一个a匹配? 我怎样才能纠正它 在javascript RegExp中需要这个,但是这不重要。在a-bZ中尝试了它,因
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(-b)周围有一群人,为什么“a-bZ”与第一个a匹配?
我怎样才能纠正它
在javascript RegExp中需要这个,但是这不重要。在
a-bZ
中尝试了它,因为(-b)?
被忽略,并且(?!Z)
与-
符号匹配
因为(-b)
是可选的,所以((a)(?!Z))
格式的每个字符串也会得到匹配。
您可以匹配(a(?!Z))|(a-b(?!Z))
但是,这将匹配a-bZ
(因为a后面跟一个非Z字符)
如果要查找字符串的所有实例,例如,a-c
不匹配(即使-
是非Z字符),可以执行以下操作:
(a(?![-Z]))|(a-b(?!Z))
如果指定开始和结束锚点,则上述正则表达式((a(-b))(?!Z))将与字符串
a-bZ
不匹配,请参见演示。由于未指定锚定,并且(-b)
是可选的,因此正则表达式引擎首先尝试在任何位置匹配a-b
,然后在看到以下Z
字母时放弃匹配。现在,由于可选的-b
,正则表达式引擎会回溯以获得匹配。现在它在a
上,字母a
后面不会紧跟着Z
,因此引擎现在匹配字母a
您可以使用原子分组使正则表达式工作。不幸的是,JavaScript正则表达式引擎不支持此功能
但是有一个技巧可以使用向前看和向后引用()来模拟其效果:
因此,在您的a-b
或只是a
情况下,这将变成:
(?=(a-b|a))\1(?!Z)
请注意,需要在组中首先提到较长的子模式a-b
,否则它将不起作用
关键机制是,前瞻查找最早、最长的子匹配,而后退引用防止引擎中的任何回溯并移动字符串中的位置,因此可以执行以下测试
(?!Z)
。由于b是可选的,所以(a(-b)
匹配为a
,然后它后面是-
,它不是Z,所以负前瞻性不匹配。这很有道理。你是对的,我把前瞻和消费混为一谈,thx.?>在JS中不受支持那么呢?thx@raina77ow,是的,这很有效,缺点是我对a和b的定义很长,所以重复b有点痛。但是看起来没有出路了。Thx也指向regex101,真的很酷。?!不使用匹配中的字符,我认为这一点值得一提。实际上,这在模式中没有任何重复-/(?=(a(-b))\1(?!Z)/
(),出于同样的原因-先尝试“前瞻”中最长的模式。对于我来说,这个答案如何不被OP接受才是真正的难题。)来得太晚了。从我的经验来看:这样的正则表达式线程通常在第一个可行的答案时死亡,OP很少考虑或认可所提供的备选方案。@raina77ow:最长的模式是首先尝试的,因为?
,比如a-b | a
的顺序意味着试验的顺序。当你让它变得懒惰时,你就会理解我的观点:/(?=(a(-b)?)\1(?!Z)/
(?=(a-b|a))\1(?!Z)