2009-06-22 128 views
7

我正在讀取一些數據文件中的程序,其中一部分格式化爲一系列記錄,每個記錄都放在方括號中。每個記錄都包含一個節標題和一系列鍵/值對。你可以改進這個C#正則表達式代碼嗎?

我最初編寫的代碼循環並提取值,但決定可以使用正則表達式更優雅地完成。下面是我的結果代碼(我剛剛在一個控制檯應用程序中入侵了它 - 所以知道變量名稱並不是那麼好,等等。

你可以提出改進建議嗎?我認爲不應該有必要做兩場比賽和子,但無法弄清楚如何做到這一切在一個大的步驟:

string input = "[section1 key1=value1 key2=value2][section2 key1=value1 key2=value2 key3=value3][section3 key1=value1]"; 

MatchCollection matches=Regex.Matches(input, @"\[[^\]]*\]"); 
foreach (Match match in matches) 
{ 
    string subinput = match.Value; 

    int firstSpace = subinput.IndexOf(' '); 
    string section = subinput.Substring(1, firstSpace-1); 
    Console.WriteLine(section); 

    MatchCollection newMatches = Regex.Matches(subinput.Substring(firstSpace + 1), @"\s*(\w+)\s*=\s*(\w+)\s*"); 
    foreach (Match newMatch in newMatches) 
    { 
     Console.WriteLine("{0}={1}", newMatch.Groups[1].Value, newMatch.Groups[2].Value); 
    } 
} 

回答

7

我更喜歡叫捕獲,漂亮的格式,和清晰度:

string input = "[section1 key1=value1 key2=value2][section2 key1=value1 key2=value2 key3=value3][section3 key1=value1]"; 
MatchCollection matches = Regex.Matches(input, @"\[ 
                (?<sectionName>\S+) 
                 (\s+                
                 (?<key>[^=]+) 
                  = 
                 (?<value>[^ \] ]+)              
                )+ 
                ]", RegexOptions.IgnorePatternWhitespace); 

foreach(Match currentMatch in matches) 
{ 
    Console.WriteLine("Section: {0}", currentMatch.Groups["sectionName"].Value); 
    CaptureCollection keys = currentMatch.Groups["key"].Captures; 
    CaptureCollection values = currentMatch.Groups["value"].Captures; 

    for(int i = 0; i < keys.Count; i++) 
    { 
     Console.WriteLine("{0}={1}", keys[i].Value, values[i].Value);   
    } 
} 
+0

不錯,我不知道如何使用IgnorePatternWhitespace選項讓你格式化正則表達式。謝謝你的提示。 – 2009-06-23 04:36:40

2

你應該能夠做到與嵌套組是這樣的:

pattern = @"\[(\S+)(\s+([^\s=]+)=([^\s\]]+))*\]" 

我沒有在C#中測試過它,或者通過匹配循環,但結果看起來正確rubular.com

+0

+1的鏈接。 – 2009-06-23 06:04:27

5

您應該利用集合來獲取每個密鑰。因此,像這樣,那麼:

 string input = "[section1 key1=value1 key2=value2][section2 key1=value1 key2=value2 key3=value3][section3 key1=value1]"; 

     Regex r = new Regex(@"(\[(\S+) (\s*\w+\s*=\s*\w+\s*)*\])", RegexOptions.Compiled); 

     foreach (Match m in r.Matches(input)) 
     { 
      Console.WriteLine(m.Groups[2].Value); 
      foreach (Capture c in m.Groups[3].Captures) 
      { 
       Console.WriteLine(c.Value); 
      } 
     } 

結果輸出:

section1 
key1=value1 
key2=value2 
section2 
key1=value1 
key2=value2 
key3=value3 
section3 
key1=value1 
-1

這將匹配所有的鍵/值對...

var input = "[section1 key1=value1 key2=value2][section2 key1=value1 key2=value2 key3=value3][section3 key1=value1]"; 

var ms = Regex.Matches(input, @"section(\d+)\s*(\w+=\w+)\s*(\w+=\w+)*"); 

foreach (Match m in ms) 
{ 
    Console.WriteLine("Section " + m.Groups[1].Value); 

    for (var i = 2; i < m.Groups.Count; i++) 
    { 
     if(!m.Groups[i].Success) continue; 
     var kvp = m.Groups[i].Value.Split('='); 
     Console.WriteLine("{0}={1}", kvp[0], kvp[1]); 
    } 
}