3

这篇文章中,它提到

确保您清楚每个字符都测试了表达式模式这一事实。而且,仅仅因为引擎在遵循模式并寻找匹配项时向前移动,它仍然会回溯并检查字符串中的每个字符,直到找到匹配项,或者如果设置了全局标志,直到检查完所有字符。

但是我在 Javascript 中测试的

"aaa@bbb".match(/a+@b+/g)

不会产生如下结果:

["aaa@bbb", "aa@bbb", "a@bbb"]

它只产生["aaa@bbb"]. 它似乎没有检查每个字符来测试模式。谁能解释一下匹配步骤?谢谢。

4

5 回答 5

4

/g并不意味着它将尝试在输入字符串中找到可能与给定模式匹配的每个可能的字符子集。这意味着一旦找到匹配项,它将继续从前一个匹配项开始搜索更多可能与模式匹配的子字符串。

例如:

"aaa@bbb ... aaaa@bbbb".match(/a+@b+/g);

会产生

["aaa@bbb", "aaaa@bbbb"]
于 2013-07-21T07:11:13.183 回答
4

这种解释混合了两个不同的概念,IMO 应该保持分开

A) 回溯

在寻找匹配项时,量词 ( ?, *, +) 的正常行为是“贪婪的”,即尽可能多地咀嚼......例如,在/(a+)([^b]+)/测试中,aaaacccc所有这些a都将成为第 1 组的一部分,即使它们当然是还匹配字符集[^b](除 之外的所有内容b)。

但是,如果抓取过多会阻止匹配,则 RE 规则要求量词“回溯”捕获更少,如果这允许表达式匹配。例如,在第 1 组(a+)([^b]+)进行测试时,aaaa只会得到 3 个as,留给第 2 组匹配。

您可以使用“非贪婪量词”(如*?, +?, )来改变这种贪婪行为??。在这种情况下,引擎会进行回溯,但含义相反:非贪婪的子表达式将尽可能少地吃掉,以允许表达式的其余部分匹配。例如(a+)(a+b+),tested withaaabbb将为组 1 和组 2 留下两个as abbb,但(a+?)(a+b+)使用相同的字符串将只a为组 1 留下一个,因为这是允许匹配剩余部分的最小值。

请注意,由于回溯,如果表达式是否匹配,贪婪/非贪婪选项不会改变,而只会改变匹配的大小和每个子表达式的大小。

B)“全局”选项

这与回溯完全无关,只是意味着搜索必须找到所有不重叠的匹配,而不是在第一个匹配处停止。这是通过找到第一个匹配项,然后在匹配项结束后重新开始搜索来完成的

请注意,每个匹配都是使用标准正则表达式规则计算的,并且不同匹配之间没有前瞻或回溯:换句话说,如果使例如贪婪匹配更短会在字符串中提供更多匹配,则不考虑此选项...即使指定了选项, a+[^b]+tested withaaaaaa也只会给出一个匹配g项,即使子字符串aa, aa,aa将是正则表达式的有效匹配项。

于 2013-07-21T07:30:28.597 回答
0

如果您不指定/g,则引擎将在找到匹配项后立即停止。

如果您指定/g,它将在比赛后继续。但是,它仍然不会产生重叠匹配,这就是您要问的。

于 2013-07-21T07:12:02.960 回答
0

这是因为。,

正则表达式尝试做什么:
所有正则表达式都将尝试匹配best match.

正则表达式不会做什么
它不会像您的情况那样匹配单个匹配的组合。

当您的"aaa@bbb".match(/a+@b+/g)方案有效时

相反,aaa@bbbHiaa@bbbHelloa@bbbSEEYOU尝试这样的事情,这会给你

aaa@bbb
aa@bbb
a@bbb
于 2013-07-21T07:12:15.573 回答
0

当使用全局标志时,它会在前一个匹配结束后开始搜索下一个匹配,以防止生成大量这样的重叠匹配。

于 2013-07-21T07:11:08.767 回答