我非常疑惑为什么会发生这种情况,并希望有人能够解释正则表达式引擎中发生的事情的机制。
在进行代码战练习时#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中也是这样做的
答案 0 :(得分:2)
那么为什么在最后的y上添加
?
意味着我不再看到任何匹配的字符?
您在开头使用的模式 - /(c?)(h?)(e?)(r?)(r?)(y?)/
- 可以匹配空字符串,因为所有子模式都是可选的(即可以匹配零次出现)。当您只查找一个匹配项(例如,在JavaScript中使用String#match
)时,您将始终获得位于字符串最开头的匹配项(因为在大多数情况下,正则表达式引擎会从左侧分析字符串右边),要么是一个空字符串(如果第一个字符不能与第一个子图案匹配),要么是一个子字符串,如果前面的或所有子图案匹配的话。
因此,berry
以b
开头。 /(c?)(h?)(e?)(r?)(r?)(y?)/
以可选c
开头,因此,b
无法与c
匹配,并且失败。 b
无法与h
,e
,r
,其他r
和y
匹配。请注意,如果您将上一个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
。