0

考虑这个正则表达式:

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

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

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

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

4

1 回答 1

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]*至少匹配(并捕获)一次,但现在它会停在那里,除非有什么东西迫使它继续。什么都没有,所以你得到三个单独的Matches,每个包含一个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]*)+?$

现在,每个匹配项必须从字符串的开头开始并在字符串的结尾结束。为了实现这一点,正则表达式引擎覆盖了 的非贪婪+?,并且您回到了一个匹配三个 Capture 的状态:

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();
  }
}
于 2013-02-15T03:27:36.987 回答