锚点和组重复

时间:2013-02-14 22:05:41

标签: .net regex

考虑这个正则表达式:

(?:([A-Z][0-9a-z]*)+?)

当应用于字符串“A1BaaC2d”时,它给了我3组:“A1”,“Baa”和“C2d”

但是当我应用起始和结束字符串锚时,即^(?:( [A-Z] [0-9a-z] *)+?)$它不再正常工作。我猜这是一个引用问题(hense额外的分组,我尝试过非捕获和原子)。但我无法解决这个问题。如何获取我的组并验证总字符串没有任何前导或尾随字符。

仅供参考,这是.net正则表达式。

1 个答案:

答案 0 :(得分:3)

让我们把它简化为基本要素:

([A-Z][0-9a-z]*)+

(我摆脱了外部的非捕获组,因为它对结果没有影响,我暂时从量词中删除了?。)你得到的是一个正则表达式一个捕获组。由于+量词,该组中的子表达式必须至少匹配一次,但默认情况下量词是贪婪的,因此它实际上与您的输入匹配三次。这是细分:

Match 1 = A1BaaC2d
Group 1 = C2d
Capture 1 = A1
Capture 2 = Baa
Capture 3 = C2d

(“组1”是指该组捕获的最终值。在大多数正则表达式/工具中,这是您将获得的所有信息; .NET的独特之处在于它允许您打破所有中间捕获。)

但是,您使用量词的非贪婪版本+?

    ([A-Z][0-9a-z]*)+?

它仍然必须匹配(和捕获)[A-Z][0-9a-z]*至少一次,但现在它停在那里,除非有什么东西迫使它继续。什么都没有,所以你得到三个单独的匹配,每个包含一个 Capture

Match 1 = A1
Group 1 = A1
Capture 1 = A1

Match 1 = Baa
Group 1 = Baa
Capture 1 = Baa

Match 1 = C2d
Group 1 = C2d
Capture 1 = C2d

然后你添加了锚点:

^([A-Z][0-9a-z]*)+?$

现在,每个匹配必须从字符串的开头开始,并在字符串的结尾处结束。要实现这一点,正则表达式引擎会覆盖+?的非贪婪,并且您将返回一个与三个捕获的匹配:

Match 1 = A1BaaC2d
Group 1 = C2d
Capture 1 = A1
Capture 2 = Baa
Capture 3 = C2d

以下是我用于生成此输出的代码的最终版本。请注意,您并不需要使用非贪婪的正则表达式; ^([A-Z][0-9a-z]*)+$也可以正常运作。

static void Main()
{
  string source = "A1BaaC2d";
  Regex r = new Regex(@"^([A-Z][0-9a-z]*)+?$");
  foreach (Match m in r.Matches(source))
  {
    int x = 1;
    Console.WriteLine(@"Match {0} = {1}", x++, m.Value);
    Console.WriteLine(@"Group 1 = {0}", m.Groups[1]);
    int y = 1;
    foreach (Capture c in m.Groups[1].Captures)
    {
      Console.WriteLine(@"Capture {0} = {1}", y++, c.Value);
    }
    Console.WriteLine();
  }
}