在Javascript中,我有一个字符串abcdef
,无法弄清楚这种奇怪的行为:
(?=abc)def
与字符串abc(?=def)
符合字符串为什么?
答案 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
上,因此匹配失败。
答案 1 :(得分:4)
(?=...)
是一个先行,换句话说就是测试右边的字符串。另请注意,前瞻是零宽度断言,不会吃掉字符。在您的第一个示例中:(?=abc)
表示必须跟abc
遇到def
。这就是模式失败的原因。
在第二个示例中,它在def
之后找到abc
,然后字符串匹配
答案 2 :(得分:2)
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")