为什么在regex char可选

时间:2016-02-19 08:59:05

标签: javascript regex regex-greedy

我非常疑惑为什么会发生这种情况,并希望有人能够解释正则表达式引擎中发生的事情的机制。

在进行代码战练习时#34;你的意思是......?"在Javascript中,我试图计算word1中有多少字符出现在word2中。我试图将每个char作为自己的匹配组进行匹配,以便稍后我可以计算数组中成功匹配的数量,并使用它来找出这两个词的相似程度。

请不要给我如何解决代码战挑战的提示,只是帮助我了解这里发生的事情。

我试过了:

'berry'.match(/(c?)(h?)(e?)(r?)(r?)(y?)/)

并且没有匹配

> ["", "", "", "", "", "", ""]

这对我来说是一个谜。搜索了Regular-expressions.info之后,?(使前面的字符可选)是贪婪的,所以尽管没有匹配对正则表达式有效,但它不应该首先被贪婪的版本打败吗?我期待着这个:

> ["", "", "", "e", "r", "r", "y"]

我尝试过的其他事情: - 樱桃匹配樱桃按预期工作

'cherry'.match(/(c?)(h?)(e?)(r?)(r?)(y?)/)
> ["cherry", "c", "h", "e", "r", "r", "y"]

cherl match cherry也像我期望的那样工作

'cherl'.match(/(c?)(h?)(e?)(r?)(r?)(y?)/)
> ["cher", "c", "h", "e", "r", "", ""]

如果我从最终?中移除y,它也会按预期运行:

'berry'.match(/(c?)(h?)(e?)(r?)(r?)(y)/)
> ["erry", "", "", "e", "r", "r", "y"]

那么为什么在最终的?上添加y意味着我不再看到任何匹配的字符?

虽然我在JS中尝试了这个,但我在PY和PCRE中也是这样做的

1 个答案:

答案 0 :(得分:2)

  

那么为什么在最后的y上添加?意味着我不再看到任何匹配的字符?

您在开头使用的模式 - /(c?)(h?)(e?)(r?)(r?)(y?)/ - 可以匹配空字符串,因为所有子模式都是可选的(即可以匹配零次出现)。当您只查找一个匹配项(例如,在JavaScript中使用String#match)时,您将始终获得位于字符串最开头的匹配项(因为在大多数情况下,正则表达式引擎会从左侧分析字符串右边),要么是一个空字符串(如果第一个字符不能与第一个子图案匹配),要么是一个子字符串,如果前面的或所有子图案匹配的话。

因此,berryb开头。 /(c?)(h?)(e?)(r?)(r?)(y?)/以可选c开头,因此,b无法与c匹配,并且失败。 b无法与her,其他ry匹配。请注意,如果您将上一个y?更改为b?,则为will get a b in the match

如果您在JS正则表达式中不使用/g(全局)标志,则引擎将仅检查一个匹配项。它会在开头找到它 - 一个空字符串,返回它并称它为一天。 If you use /g,它会检查所有位置,第二场比赛会为您提供所需的结果。但是,当您使用String#match()基于/g的正则表达式时,您将丢失捕获的子字符串。使用RegExp#exec()可以访问这些子匹配。

请注意/(c?)(h?)(e?)(r?)(r?)(y)/为您提供匹配,因为上一个y 必须,且该模式不再匹配空字符串。因此,当引擎在b中看到berry时,它会使匹配失败,继续检查e之前的下一个位置,并在那里找到匹配项。因此,在这种情况下不需要/g