为什么这个表达不遵循贪婪的方法?

0 c# regex regex-greedy

为什么这个表达式不遵循贪婪的方法?

string input = @"cool  man! your  dog can walk on water ";
string pattern = @"cool (?<cool>(.*))    (?<h>((dog)*)) (?(h)(?<dog>(.*))) ";

MatchCollection matches = Regex.Matches(input, pattern, RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace);


foreach (Match match in matches)
{
    Console.WriteLine("cool=" + match.Groups["cool"].Value);
    Console.WriteLine("dog=" + match.Groups["dog"].Value);
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

输出:

酷=男人!你的狗可以在水上行走
狗=

你可以观察到:(狗)组匹配0次.但是,因为,*是贪婪的,为什么不尝试找到(狗)的最大匹配为1?

有线索吗?

Ala*_*ore 7

第一个.*最初匹配整个字符串.然后正则表达式引擎确定是否需要退出以匹配正则表达式的其余部分.但是,(?<h>((dog)*))并且 (?(h)(?<dog>(.*)))可以合法地匹配零个字符,因此不需要回溯(就此.*而言).尝试.*?在该部分使用非贪婪.

编辑(响应下面答案中发布的其他信息):好的,用.*非贪婪替换第一个.*? 确实有效果,而不是你想要的那个."酷"这个词之后的所有内容都是在小组中被捕获的<cool>,现在它被分组捕获<dog>.这是发生了什么:

在匹配"酷"这个词之后,(?<cool>(.*?))最初不匹配任何东西(与贪婪行为相反),并(?<h>((dog)*))尝试匹配.无论在哪里尝试,这部分都会成功,因为它可以匹配"狗"或空字符串.这意味着条件表达式(?(h)...)将始终求值true,因此它继续并与输入的其余部分匹配(?<dog>(.*)).

据我了解,你想在命名组中"酷"后匹配所有内容<cool>,除非该字符串包含单词"dog"; 那么你想捕获命名组中"dog"之后的所有内容<dog>.你试图使用条件,但它不是真正的正确工具.这样做:

string pattern = @"cool (?<cool>.*?) (dog (?<dog>.*))?$";
Run Code Online (Sandbox Code Playgroud)

关键在于$最后; 它迫使非贪婪的.*?人保持匹配,直到它到达字符串的末尾.因为它不贪婪,所以(dog (?<dog>.*))在使用每个字符之前,它会尝试匹配正则表达式的下一部分.如果单词"dog"在那里,则其余的字符串将被消耗(?<dog>.*); 如果没有,正则表达式仍然成功,因为?使整个部分可选.