考虑这个正则表达式:
(?:([A-Z][0-9a-z]*)+?)
当应用于字符串“A1BaaC2d”时,它给了我 3 个组:“A1”、“Baa”和“C2d”
但是,当我应用开始和结束字符串锚点时,即 ^(?:([AZ][0-9a-z]*)+?)$ 它不再正常工作。我猜这是一个参考问题(因此我尝试过的额外分组是非捕获和原子的)。但我无法完全解决。如何获取我的组并验证总字符串没有任何前导或尾随字符。
仅供参考,这是一个 .net 正则表达式。
让我们将其简化为要点:
([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();
}
}