对于.NET的正则表达式语言,“组”和“捕获”之间的区别让我有些模糊。考虑以下C#代码:
MatchCollection matches = Regex.Matches("{Q}", @"^\{([A-Z])\}$");
我希望这会导致字母’Q’的单个捕获,但是如果我打印返回的属性,则会MatchCollection看到:
MatchCollection
matches.Count: 1 matches[0].Value: {Q} matches[0].Captures.Count: 1 matches[0].Captures[0].Value: {Q} matches[0].Groups.Count: 2 matches[0].Groups[0].Value: {Q} matches[0].Groups[0].Captures.Count: 1 matches[0].Groups[0].Captures[0].Value: {Q} matches[0].Groups[1].Value: Q matches[0].Groups[1].Captures.Count: 1 matches[0].Groups[1].Captures[0].Value: Q
这到底是怎么回事?我知道整个比赛也都有机会,但是小组如何进入?为什么不matches[0].Captures包括字母“ Q”的捕获?
matches[0].Captures
您不会是第一个对此感到困惑的人。以下是著名的杰弗里·弗里德尔(Jeffrey Friedl)所说的话(第437页以上):
根据您的观点,它要么为比赛结果添加了有趣的新维度,要么使您感到困惑和膨胀。
进一步:
Group对象和Capture对象之间的主要区别在于,每个Group对象都包含一个Captures集合,这些Collections表示 该组在匹配过程中的所有 中间 匹配项以及该组匹配的最终文本。
几页后,这就是他的结论:
在了解了.NET文档并真正理解了这些对象的内容之后,我对它们有了不同的看法。一方面,这是一个有趣的创新[..];另一方面,它似乎增加了大多数情况下不会使用的功能的效率负担[..]
换句话说:它们非常相似,但是偶尔会碰巧有它们的用处。在长出另一头灰色胡须之前,您甚至可能喜欢Captures …
由于以上内容和其他文章中的内容均未真正回答您的问题,请考虑以下内容。将Captures视为一种历史跟踪器。当正则表达式匹配时,它从左到右遍历字符串(暂时忽略回溯),当遇到匹配的捕获括号时,它将存储在$x(x是任何数字)中,比方说$1。
$x
$1
普通的正则表达式引擎在要重复捕获括号时会丢弃当前值$1,并将其替换为新值。不是.NET,它将保留此历史记录并将其放置在.NET中Captures[0]。
Captures[0]
如果我们将您的正则表达式更改为如下所示:
MatchCollection matches = Regex.Matches("{Q}{R}{S}", @"(\{[A-Z]\})+");
您会注意到第一个Group有一个Captures(第一个组始终是整个匹配项,即等于$0),第二个将保持{S},即只有最后一个匹配组。然而,这里的渔获物,如果你想找到另外两个锁扣,他们在Captures,它包含了所有中介捕获的{Q} {R}和{S}。
Group
Captures
$0
{S}
{Q}
{R}
如果您想知道如何从多重捕获(仅显示最后一个匹配项与字符串中明显存在的单个捕获项)中获得收益,则必须使用Captures。
关于最后一个问题的最后一句话:总比赛总有一个总夺球,不要将其与各个组混合使用。 捕获只是在小组内部有趣。