在C#正则表达式中,为什么初始匹配会显示在组中?

时间:2010-02-11 22:22:08

标签: c# regex

因此,如果我写一个正则表达式,它匹配我可以得到匹配或我可以访问其组。这似乎是反直觉的,因为组在表达式中用大括号“(”和“)”定义。看起来它不仅错误而且多余。谁知道为什么?

Regex quickCheck = new Regex(@"(\D+)\d+");
string source = "abc123";

m.Value        //Equals source
m.Groups.Count //Equals 2
m.Groups[0])   //Equals source
m.Groups[1])   //Equals "abc"

8 个答案:

答案 0 :(得分:4)

我同意 - 这有点奇怪,但我认为有很好的理由。

正则表达式Match本身是Group,而Capture又是Match.Value

但是Capture.Value(或实际上是Value)仅在字符串中存在一个匹配时才有效 - 如果您匹配模式的多个实例,那么根据定义它可以不回报一切。实际上 - 匹配时的Groups[0]属性仅在匹配时方便。

但是要澄清将整个匹配传递给[TestMethod] public void UnMinifyExample() { string toUnMinify = "{int somevalue = 0; /*init the value*/} /* end */"; string result = Regex.Replace(toUnMinify, @"(;|})\s*(/\*[^*]*?\*/)?\s*", "$0\n"); Assert.AreEqual("{int somevalue = 0; /*init the value*/\n} /* end */\n", result); } 的行为在哪里是有意义的 - 考虑一个天真的代码unminifier的这个(人为的)示例:

Groups[0]

正则表达式匹配将在语句结尾处保留/ * * / comments,之后放置换行符 - 但适用于任何一个;或}行结尾。

好的 - 你可能想知道为什么你会用正则表达式来做这件事 - 但是幽默我:)

如果此正则表达式的匹配项生成的Groups[0]不是整个捕获 - 那么单个调用替换将无法实现 - 您的问题可能会问为什么整场比赛进入{{1}}而不是反过来!

答案 1 :(得分:4)

Match的文档说第一组始终是整个匹配,因此它不是实现细节。

答案 2 :(得分:2)

历史就是全部。在Perl 5中,捕获组的内容存储在特殊变量$1$2等中,但C#,Java和其他人将它们存储在一个数组(或类似数组的结构)中。为了保持与Perl的命名约定(已被其他几种语言复制)的兼容性,第一组存储在第一个元素中,第二个存储在第二个元素中,等等。这使元素零自由,所以为什么不在那里存储完整匹配?

仅供参考,Perl 6采用了一种新约定,其中第一个捕获组编号为零而不是一个。我确定不是只是为了惹恼我们。 ;)

答案 3 :(得分:1)

最有可能的是,您可以使用“$ 0”来表示替换表达式中的匹配,并使用“$ 1”表示第一组匹配等。

答案 4 :(得分:0)

我不认为除了写这篇文章的人选择这个作为实现细节之外,确实有一个答案。只要你记得第一组总是等于源字符串你应该没问题: - )

答案 5 :(得分:0)

不确定原因,但如果使用命名组,则可以设置选项RegExOptions.ExplicitCapture,并且不应将源包含为第一组。

答案 6 :(得分:0)

它可能是多余的,但它有一些不错的属性。

例如,这意味着捕获组的工作方式与其他正则表达式引擎相同 - 第一个捕获组对应于“1”,依此类推。

答案 7 :(得分:0)

反向引用是基于一个的,例如\1$1是第一个带括号的子表达式,依此类推。如图所示,一个人毫无思想地映射到另一个人。

另外值得注意的是:m.Groups["0"]为您提供了完整匹配的子字符串,因此如果您正在迭代"0",请务必跳过regex.GetGroupNames()