为什么“abcdef”不匹配(?= abc)def但匹配abc(?= def)?

时间:2013-06-10 01:17:43

标签: javascript regex pcre

在Javascript中,我有一个字符串abcdef,无法弄清楚这种奇怪的行为:

  • (?=abc)def与字符串
  • 不匹配
  • abc(?=def)符合字符串

为什么?

4 个答案:

答案 0 :(得分:19)

(?=abc)def中,(?=abc)捕获的宽度为零,并且在成功匹配后不会在输入字符串中向前移动光标。该结构只是说明一下接下来的三个字符,看看它们是abc,如果它们然后检查这些字符是否def。此时比赛失败..

您需要了解正则表达式引擎如何完成匹配。考虑输入字符串abcdef和正则表达式abc(?=def)。引擎通过匹配a启动,然后将输入字符串中的光标移动到下一个字符并尝试匹配b,因为输入字符串中的光标在b匹配成功。然后引擎将光标移动到输入字符串内,并尝试匹配c,因为光标位于输入字符串中c匹配成功,输入字符串中的光标再次出现转移到下一个角色。现在引擎遇到(?=def)此时引擎只是向前看,看看光标在输入sting中的下三个字符实际上是def而不移动光标,它们是并且匹配成功完成。

现在考虑输入字符串xyz和正则表达式x(?=y)Z。正则表达式引擎将光标放在输入字符串中的第一个字母上并检查它是否为x并找到x,因此它将光标移动到输入字符串中的下一个字符。现在,它会查看下一个字符是否为y,但引擎不会移动输入文本光标前言,因此输入文本中的光标会保留在y上。接下来,引擎会查看光标是否在字母z上,但由于输入文本中的光标仍在字母y上,因此匹配失败。

您可以在http://www.regular-expressions.info/lookaround.html

上阅读更多有关正面和负面前瞻的内容

答案 1 :(得分:4)

(?=...)是一个先行,换句话说就是测试右边的字符串。另请注意,前瞻是零宽度断言,不会吃掉字符。在您的第一个示例中:(?=abc)表示必须跟abc 遇到def。这就是模式失败的原因。

在第二个示例中,它在def之后找到abc,然后字符串匹配

答案 2 :(得分:2)

javascript

MDN definition of lookaheads

  

x(?=y)
  仅当'x'后跟'y'时才匹配'x'。这称为前瞻。

     

例如,/Jack(?=Sprat)/只有在跟随'Sprat'时才匹配'Jack'。 /Jack(?=Sprat|Frost)/只有在跟随'Sprat'或'Frost'时才匹配'Jack'。但是,'Sprat'和'Frost'都不是比赛结果的一部分。

因此(?=y)前面有另一个语句,在本例中是一个空字符串,只有当第一个语句后跟第二个语句时它才会匹配。如果没有前导语句,表达式(?="abc")将匹配前3个字符abc而不捕获它们,然后再次检查以查看这些字符是否为def,这将失败。

答案 3 :(得分:2)

根据您对我的评论的回复,我认为您想要的是positive look-behind

(?<=abc)def

修改

由于您使用的是JavaScript(抱歉,我只是阅读了您的问题 - 我没有查看标记),为什么不使用常规捕获组并在替换模式中包含匹配项?

"abcdef".replace(/(abc)def/, "$1")