小编典典

.NET正则表达式中的“组”和“捕获”之间有什么区别?

c#

对于.NET的正则表达式语言,“组”和“捕获”之间的区别让我有些模糊。考虑以下C#代码:

MatchCollection matches = Regex.Matches("{Q}", @"^\{([A-Z])\}$");

我希望这会导致字母’Q’的单个捕获,但是如果我打印返回的属性,则会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”的捕获?


阅读 272

收藏
2020-05-19

共1个答案

小编典典

您不会是第一个对此感到困惑的人。以下是著名的杰弗里·弗里德尔(Jeffrey
Friedl
)所说的话(第437页以上):

根据您的观点,它要么为比赛结果添加了有趣的新维度,要么使您感到困惑和膨胀。

进一步:

Group对象和Capture对象之间的主要区别在于,每个Group对象都包含一个Captures集合,这些Collections表示
该组在匹配过程中的所有 中间 匹配项以及该组匹配的最终文本。

几页后,这就是他的结论:

在了解了.NET文档并真正理解了这些对象的内容之后,我对它们有了不同的看法。一方面,这是一个有趣的创新[..];另一方面,它似乎增加了大多数情况下不会使用的功能的效率负担[..]

换句话说:它们非常相似,但是偶尔会碰巧有它们的用处。在长出另一头灰色胡须之前,您甚至可能喜欢Captures …


由于以上内容和其他文章中的内容均未真正回答您的问题,请考虑以下内容。将Captures视为一种历史跟踪器。当正则表达式匹配时,它从左到右遍历字符串(暂时忽略回溯),当遇到匹配的捕获括号时,它将存储在$x(x是任何数字)中,比方说$1

普通的正则表达式引擎在要重复捕获括号时会丢弃当前值$1,并将其替换为新值。不是.NET,它将保留此历史记录并将其放置在.NET中Captures[0]

如果我们将您的正则表达式更改为如下所示:

MatchCollection matches = Regex.Matches("{Q}{R}{S}", @"(\{[A-Z]\})+");

您会注意到第一个Group有一个Captures(第一个组始终是整个匹配项,即等于$0),第二个将保持{S},即只有最后一个匹配组。然而,这里的渔获物,如果你想找到另外两个锁扣,他们在Captures,它包含了所有中介捕获的{Q}
{R}{S}

如果您想知道如何从多重捕获(仅显示最后一个匹配项与字符串中明显存在的单个捕获项)中获得收益,则必须使用Captures

关于最后一个问题的最后一句话:总比赛总有一个总夺球,不要将其与各个组混合使用。 捕获只是在小组内部有趣

2020-05-19