一尘不染

为什么简单的。*?非贪婪正则表达式在比赛之前贪婪地包含其他字符?

javascript

我有一个非常简单的正则表达式与此类似:

HOHO.*?_HO_

有了这个测试字符串…

fiwgu_HOHO_HOHO_HOHOrgh_HOHO_feh_HOHO___HO_fbguyev

  • 我希望它能匹配_HOHO___HO_(最短匹配,非贪婪)
  • 相反,它匹配_HOHO_HOHO_HOHOrgh_HOHO_feh_HOHO___HO_(最长的匹配,看起来很贪婪)。

为什么?如何使它匹配最短的匹配?

添加和删​​除的?结果相同。

编辑
-更好的测试字符串,显示为什么[^HOHO]不起作用:fiwgu_HOHO_HOHO_HOHOrgh_HOHO_feh_HOHO_H_O_H_O_HO_fbguye


我只能想到的是,它可能多次匹配-但只有一个匹配_HO_,所以我不明白为什么它没有采用以结尾的最短匹配_HO_,而丢弃了其余匹配。

我浏览了所有标题为“非贪婪正则表达式贪婪”之类的问题,但它们似乎都存在其他问题。


阅读 325

收藏
2020-05-01

共1个答案

一尘不染

如果一个左手比赛有很多左手比赛,它将始终从到达的第一个开始(实际上会给出 最长的 比赛)。

本质上,它一次穿过字符串一个字符,询问“此字符是否匹配?如果匹配,则匹配最短的字符并结束。如果不匹配,则移动到下一个字符,重复”。我希望它是“此字符串中是否有任何匹配项?如果是,则匹配所有字符串中最短的一个”。


通过用.表示“不是左侧匹配”的否定替换,可以在两个方向上近似表示非贪婪的正则表达式。要否定这样的字符串,需要否定先行和不捕获组,但这就像将字符串放入一样简单(?:(?!).)。例如,(?:(?!HOHO).)

例如,左右等价于HOHO.*?_HO_非贪婪的等价于:

HOHO(?:(?!HOHO).)*?_HO_

因此,正则表达式引擎实质上是通过每个字符来进行如下操作:

  • HOHO -这与左侧匹配吗?
  • (?:(?!HOHO).)* -如果是这样,我能否到达右侧而不重复左侧?
  • _HO_ -如果是这样,抓住所有东西,直到进行右侧比赛
  • ?``*或上的修饰符+-如果有多个右手匹配项,请选择最接近的一个
2020-05-01