2012-10-20 14 views
1
 Regex regexObj = new Regex(
     @"([A-Za-z_][A-Za-z_0-9]*)(:)(([-+*%])?(\d*\.?\d*)?)*" 
      , RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace); 

     var subjectString = "a:123+456;b:456;"; 
     Match matchResults = regexObj.Match(subjectString); 
     while (matchResults.Success) { 
      for (int i = 1; i < matchResults.Groups.Count; i++) { 
       Group grp = matchResults.Groups[i]; 
       if (grp.Success) { 
        Console.WriteLine("st:" + grp.Index + ", len:" + grp.Length + ", val:" + grp.Value); 
       } 
      } 
      matchResults = matchResults.NextMatch(); 
     } 

输出:这个正则表达式怎么会不会为数字产生一个组/捕获?

ST:0,LEN:2,VAL:.A

ST:2,LEN:1,VAL ::

ST:6,LEN:0, VAL:

ST:6,LEN:0,VAL:

回答

2

因为通过允许考虑 “” 为\d*有效履行,数量不断发生之前,您的采集完成。

您应该至少指定一个数字为强制(+)而不是可选(*),以使其开始捕获组。

要澄清,正则表达式编译时没有错误,但没有为特定组捕获任何内容,这并不意味着匹配不成功。

这意味着比赛成功尽管已捕获任何东西。这意味着你正在让它在设计上超越这个群体。

例如,在你自己的正则表达式中:(([-+*%])?(\d*\.?\d*)?)*你是这样说的:我期待一些可选的符号后跟一个十进制数,尽管这也是可选的。如果没有发现任何东西,那可以,但是,亲爱的RegExp引擎,请不要打扰你自己,因为我不在乎这是否发生。

让我们进一步打破这:

  • \d*\.\d*意味着任何有任意数量的数字(包括没有)与之间的点。所以,0.,.,.123,都是有效匹配,以及2.1
  • 通过使可选的,你是说,即使是是没有必要的,因此,(\d*\.\d*)?将匹配""(空字符串)。
  • 通过书写([-+*%])?(\d*\.?\d*)?你是说应该在上面的字符串匹配之前发生任何事情,它必须是四个指示符号之一。但是,你并不是必须这样做(因为?)。另外,由于上述组可以匹配空字符串,所以如果引擎不能成功地将字符串匹配到任何有用的字符串,则任何指示的四个符号的存在都意味着该组仍然会成功匹配。它的全部,包括数字。
  • 现在,通过将以前的定义分组为(([-+*%])?(\d*\.?\d*)?)*,您甚至可以做出这样的选择,基本上告诉正则表达式引擎,如果它看起来没有比这个定义的开头更接近答案,那么它就没关系。

那么,你应该如何继续?你应该什么时候让团队成为可选的?您应该小心地选择一个小组,只要小心谨慎,知道如果引擎未能匹配这个小组的任何内容,声明仍然有效,并且您不关心这个值。

另外,作为一个附注,你不应该捕获一切。只捕获对你来说很重要的值,因为引擎将为您在内存中请求的任何组保留(start,length)对,这会花费您的性能。而不是正常的分组(),使用非捕获组指标(?:)这将允许您分组和更高级别的控制,同时保留内存。

另一个用途捕获组的,是当你想引用正则表达式匹配的内容:

<(\w+)>.*?</\1> 

这将捕获与其匹配的结束标记的XML标签。还要注意,上面的例子仅用于演示,一般来说,使用正则表达式解析任何类型的层次文档(除了最常见的表达方式)是大写B,大写I,坏主意。

+0

非常感谢。改变了一个角色,现在它可以工作。顺便说一句:当你找回长度为零的组时,我认为这只意味着该可选组没有成功匹配? – sgtz

+0

我刚刚更新了信息和详细信息,这些信息和详细信息可能会给您(可能)更多的见解,并会在此评论中回答您的问题。 –

相关问题