2012-10-20 15 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

我剛剛更新了信息和詳細信息,這些信息和詳細信息可能會給您(可能)更多的見解,並會在此評論中回答您的問題。 –

相關問題