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