这个正则表达式有什么问题 - 与勉强量词有关?

3

有人知道为什么这个JavaScript代码不起作用吗?(已在Chrome和Firefox中尝试过):

console.log('"my name is"'.match(/"?(.*?)"?/));

输出以下内容:

[""", "", index: 0, input: ""my name is""] 

I expected this:

[""my name is"", "my name is", index: 0, input: ""my name is""]

我不想尝试其他解决问题的方法,而且这也不是我尝试达成目标的完整解决方案(我现在已经用稍微不同的方法实现了)- 我只是想知道为什么匹配失败。
我期望勉强量词匹配一切,但不包括最后一个引号。我不明白为什么表达式未能匹配任何内容?
5个回答

6
考虑以下内容:
> "foo".match(/.*?/)
[""]

"?"告诉正则表达式尽可能匹配最少的字符,一个空字符串是最好的匹配结果。同样地,"
> "foo".match(/x/)
null
> "foo".match(/x?/)
[""]

可选模式永远不会失败,可以匹配其内容或空字符串。

在你的例子中,它首先匹配引用,然后使用(.*?)匹配一个空字符串和(另一个)空字符串与"?。由于两个测试都成功了,它不会再往下查找,结果就是一个引用。


4
问题在于你的模式中,包括周围的引号在内,都是可选的。这意味着它同样可以匹配一个空字符串。那么正则表达式引擎里面到底发生了什么?
- 引擎尝试匹配第一个"?。没问题,它匹配了字符串中的第一个"。 - 引擎继续匹配模式的下一部分.*?。好吧,第一个"后面的零长度子字符串也能匹配上,所以引擎继续往下走。 - 引擎移动到模式的最后一部分"?。下一个字符是m,所以它不能匹配,但这没关系,因为最后一个"是可选的,所以它就不会被捕获。
因此,第一个匹配结果只是第一个"

我没有注意到我的输出开头有3个引号,而不是2个,这应该是我的重要提示! - Dan King

3

你的正则表达式可以匹配任何东西(只要没有换行符)。

  • "?:无限制(可以为空,但如果可能则不会为空)
  • .*? :没有任何限制,可以是整个字符串甚至是空字符串
  • "?:无限制(可以为空)

该表达式未能匹配任何内容:第一个匹配项是"


1
当你说.*?时,实际上是要求JavaScript匹配0到无限次的匹配,但接着你立即使用?来控制它,这意味着非贪婪搜索。只需删除其中的?,你就应该没问题了。
var regEx = /"?.*"?/;
console.log('"my name is"'.match(regEx)[0]);
console.log('my name is'.match(regEx)[0]);

这个正则表达式将匹配包含或不包含 " 的字符串。

“我只是想知道为什么匹配失败。” - Denys Séguret

0
你可以使用这段代码:
console.log('"my name is"'.match(/"?(.*)\"?/));

结果:

[""my name is"", "my name is"", index: 0, input: ""my name is""] 

问题解释:

REGEX:     /"?(.*)?"?/g

你的代码中出现了(.*)?问题,这是一种重复捕获组

重复捕获组只会捕获最后一次迭代。将一个捕获组放在重复组周围以捕获所有迭代,或者如果您不关心数据,则使用非捕获组。

由于你的输入是"my name is",使用(.)*将捕获"my name is"

但是在(.*)?的情况下,由于它是重复捕获,它只会捕获最后一次迭代,即""

请参考重复捕获组获取更多详细信息。


1
引用原帖: 我不对解决问题的替代方法感兴趣[...] 我只对为什么匹配失败感兴趣。 - KeyNone
我更新了我的答案。希望你能理解原因。 - Sujith PS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接