2009-06-22 7 views
7

एक प्रोग्राम में मैं कुछ डेटा फ़ाइलों में पढ़ रहा हूं, जिनमें से कुछ वर्ग स्क्वायर ब्रैकेट में रिकॉर्ड की श्रृंखला के रूप में स्वरूपित हैं। प्रत्येक रिकॉर्ड में एक सेक्शन शीर्षक और कुंजी/मूल्य जोड़े की एक श्रृंखला होती है।क्या आप इस सी # नियमित अभिव्यक्ति कोड को बेहतर बना सकते हैं?

मैंने मूल रूप से मूल्यों को लूप करने और मूल्य निकालने के लिए कोड लिखा था, लेकिन निर्णय लिया कि इसे नियमित अभिव्यक्तियों का उपयोग करके अधिक सुंदर ढंग से किया जा सकता है। नीचे मेरा परिणाम कोड है (मैंने अभी इसे कंसोल ऐप में अभी हैक किया है - इसलिए पता है कि परिवर्तनीय नाम उस महान नहीं हैं, आदि

क्या आप सुधार का सुझाव दे सकते हैं? मुझे लगता है कि ऐसा करना आवश्यक नहीं होना चाहिए दो मैचों और सबस्ट्रिंग, लेकिन समझ नहीं कैसे एक बड़ा कदम में यह सब करने के लिए:

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 विकल्प का उपयोग करने के बारे में पता नहीं था। पारितोषिक के लिए धन्यवाद। रीडेक्सऑप्शन के लिए –

+0

+1 फिर से पढ़ने योग्यता के लिए IgnorePatternWhitespace हाँ –

+0

+1 मैं भी कैप्चर नाम पसंद करता हूं। वे कोड को पठनीय और समझने में आसान बनाते हैं। –

2

आप इस तरह नेस्टेड समूहों के साथ कुछ करने के लिए सक्षम होना चाहिए:

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

मैं इसे सी # में परीक्षण नहीं किया है या मैचों के माध्यम से looped है, लेकिन परिणामपर सही लग रहे हैं

+0

लिंक के लिए +1। –

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]); 
    } 
} 
संबंधित मुद्दे