2009-12-26 91 views
0

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

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(); 
} 

输出:

 
cool= man! your dog can walk on water 
dog= 

正如你可以看到:自 (狗)组匹配0 times.But,*是贪婪的,为何它没有试图找到最大匹配(狗)是1吗?

任何线索?

+0

?限制贪婪 – 2009-12-26 11:00:32

回答

7

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

EDIT(响应张贴在下面的答案的其他信息):好,与非贪婪.*?更换第一.*确实有效果,只是你不想要的。在“cool”之后的所有内容都在<cool>之前被捕获,现在它被捕获在组<dog>中。发生了什么事情:

“cool”这个单词匹配后,(?<cool>(.*?))最初与什么都没有匹配(与贪婪行为相反),并且(?<h>((dog)*))尝试匹配。这部分将永远成功无论它被试用,因为它可以匹配“狗”或空字符串。这意味着(?(h)...)中的条件表达式将始终评估为true,因此它继续前进,并将其余输入与(?<dog>(.*))进行匹配。

据我所知,你希望匹配命名组<cool>中的“酷”之后的所有内容,除非该字符串包含单词“dog”;那么你想要在名为<dog>的“狗”之后捕获所有内容。你正在尝试使用conditional,但它并不是真正的正确工具。只要这样做:

string pattern = @"cool (?<cool>.*?) (dog (?<dog>.*))?$"; 

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

0

我确实试过非贪婪(.*?)但它没有效果,这是非贪婪的明显(.*?)代表{0,1}。因为即使零个字符匹配在这里,所以没有效果。

任何想法如何纠正它。我的意思是,我想捕捉的字符串,然后(dog)如果目前有或者前一组将捕捉到的字符串(cool(.*))

的问题是,(dog)是可选的,如果它的存在,我们需要它后面的字符串。

使用(dog)?没有任何作用,因为它再次匹配零个字符。

谢谢。

+0

我认为你对非贪婪量词有错误的想法;阅读这个:http://www.regular-expressions.info/repeat.html其余的,看我的编辑我的原始答案。 – 2009-12-28 08:23:57

相关问题