我很困惑为什么会这样,希望有人能解释正则表达式引擎中发生的事情的机制。
在进行代码战练习时“您的意思是……?”在 Javascript 中,我试图计算 word1 中有多少字符出现在 word2 中。我尝试将每个字符作为其自己的匹配组进行匹配,以便稍后我可以计算数组中成功匹配的数量,并使用它来找出这两个词的相似程度。
请不要给我提示如何解决 codewars 挑战,只是帮助我理解这里发生了什么。
我试过:
'berry'.match(/(c?)(h?)(e?)(r?)(r?)(y?)/)
没有匹配到
> ["", "", "", "", "", "", ""]
这对我来说是个谜。搜索 Regular-expressions.info 后,?
(使前面的字符可选)是贪婪的,所以虽然没有匹配对正则表达式有效,但它不应该首先被贪婪版本打败吗?我期待这个:
> ["", "", "", "e", "r", "r", "y"]
我尝试过的其他事情: - cherry match cherry 工作正常
'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 中得到了相同的结果
最佳答案
So why does adding a
?
onto the final y mean I no longer see any matched characters?
您一开始使用的模式 - /(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 .
如果你不使用/g
(全局)标志在 JS 正则表达式中,引擎将只检查一个匹配项。它会在开头找到它 - 一个空字符串,返回它并收工。 If you use /g
,它将检查所有位置,第二场比赛将为您提供所需的结果。但是,当您使用 String#match()
与 /g
基于正则表达式,您将丢失捕获的子字符串。使用 RegExp#exec()
能够访问这些子匹配项。
请注意 /(c?)(h?)(e?)(r?)(r?)(y)/
给你匹配,因为最后一个 y
是强制性的并且模式不能再匹配空字符串。因此,当引擎看到 b
在berry
,匹配失败,继续检查 e
之前的下一个位置, 并在那里找到匹配项。因此,没有 /g
在这种情况下是必要的。
关于javascript - 为什么在 regex char 可选时找不到匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35501184/