2013-03-02 6 views
8

मैं डेटा निम्न प्रकार पर निम्नलिखित RegexRegex सी # में गैर पर कब्जा समूह

JOINTS.*\s*(?:(\d*\s*\S*\s*\S*\s*\S*)\r\n\s*)* 

उपयोग कर रहा हूँ:

JOINTS    DISPL.-X    DISPL.-Y    ROTATION 


    1   0.000000E+00   0.975415E+01   0.616921E+01 
    2   0.000000E+00   0.000000E+00   0.000000E+00 

विचार दो समूहों को निकालने के लिए, प्रत्येक एक लाइन युक्त

string jointPattern = @"JOINTS.*\s*(?:(\d*\s*\S*\s*\S*\s*\S*)\r\n\s*)*"; 
MatchCollection mc = Regex.Matches(outFileSection, jointPattern); 
foreach (Capture c in mc[0].Captures) 
{ 
    JointOutput j = new JointOutput(); 
    string[] vals = c.Value.Split(); 
    j.Joint = int.Parse(vals[0]) - 1; 
    j.XDisplacement = float.Parse(vals[1]); 
    j.YDisplacement = float.Parse(vals[2]); 
    j.Rotation = float.Parse(vals[3]); 
    joints.Add(j); 
} 

बहरहाल, यह काम नहीं करता है: इस प्रकार सी # कोड है (संयुक्त संख्या, 1, 2, आदि के साथ शुरू) के बजाय दो कब्जे वाले समूहों (अंदरूनी समूह) को लौटाना, यह एक समूह देता है: संपूर्ण ब्लॉक, कॉलम हेडर सहित। ऐसा क्यों होता है? सी # असंबद्ध समूहों के साथ अलग-अलग सौदे करता है?

अंत में, RegExes ऐसा करने का सबसे अच्छा तरीका है? (मुझे वास्तव में ऐसा लगता है कि मुझे अब दो समस्याएं हैं।)

उत्तर

8

mc[0].Capturesmc[0].Groups[0].Captures के बराबर है। Groups[0] हमेशा पूरे मैच को संदर्भित करता है, इसलिए इसमें केवल एक ही कैप्चर होगा। जिस भाग को आप ढूंढ रहे हैं उसे समूह # 1 में कैप्चर किया गया है, इसलिए आपको mc[0].Groups[1].Captures का उपयोग करना चाहिए।

लेकिन आपका रेगेक्स पूरे प्रयास को एक प्रयास में मिलान करने के लिए डिज़ाइन किया गया है, इसलिए Matches() विधि हमेशा मैच में एक मैच के साथ मैचकॉलेक्शन लौटाएगी (मान लीजिए कि मैच सफल है)। साथ ही आप Match() बजाय का उपयोग हो सकता है:

Match m = Regex.Match(source, jointPattern); 
    if (m.Success) 
    { 
    foreach (Capture c in m.Groups[1].Captures) 
    { 
     Console.WriteLine(c.Value); 
    } 
    } 

उत्पादन:

1   0.000000E+00   0.975415E+01   0.616921E+01 
2   0.000000E+00   0.000000E+00   0.000000E+00 
+0

आप जानते हैं, मैंने वास्तव में एमएसडीएन की जांच की कि 'कैप्चर' संपत्ति कैसे काम करती है (मैंने इसे कभी भी इस्तेमाल नहीं किया है), और मैंने यह नहीं देखा कि यह समूह 0 को संदर्भित करता है (जो स्पष्ट रूप से कर्कश का मुख्य कारण है ओपी)। +1! – Cameron

1

दो समस्याएं हैं: दोहराने वाला भाग (?:...) ठीक से मेल नहीं खाता है; और .* लालची है और सभी इनपुट का उपभोग करता है, इसलिए दोहराने वाला हिस्सा कभी भी मेल नहीं खाता है।

उपयोग इस बजाय:

JOINTS.*?[\r\n]+(?:\s*(\d+\s*\S*\s*\S*\s*\S*)[\r\n\s]*)* 

यह एक गैर लालची प्रमुख हिस्सा है कि लाइन मिलान हिस्सा एक नई लाइन (एक शीर्षक के बीच में नहीं) पर शुरू होता है सुनिश्चित करता है, और में [\r\n\s]* का उपयोग करता है अगर आप उम्मीद करते हैं तो न्यूलाइन बिल्कुल ठीक नहीं है।

व्यक्तिगत रूप से, मैं इसके लिए regexes का उपयोग करता हूं, लेकिन मुझे regexes पसंद है :-) यदि आपको पता है कि स्ट्रिंग की संरचना हमेशा [शीर्षक] [newline] [newline] [line] हो तो शायद यह और भी हो सीधा (अगर कम लचीला) केवल न्यूलाइन पर विभाजित करने और तदनुसार प्रक्रिया करने के लिए।

अंत में, आप अपने नियमित अभिव्यक्तियों को डीबग करने में सहायता के लिए regex101.com या कई अन्य रेगेक्स परीक्षण साइटों का उपयोग कर सकते हैं।

+0

नहीं, अभी भी काम नहीं करता।यह एक बड़ा कैप्चर समूह देता है जिसमें जॉइन से लेकर अंतिम फ़्लोटिंग पॉइंट नंबर तक सब कुछ शामिल है। – ian93

+0

@ ian93: इसे अभी आज़माएं, मैंने न्यूलाइन हैंडलिंग/लाइन हैंडलिंग की शुरुआत तय की है। साथ ही, यदि आप जानते हैं कि केवल एक मैच होने जा रहा है, तो आप 'मिलान' का उपयोग क्यों कर रहे हैं? – Cameron

+0

@ कैमरॉन यह केवल पहले मैच करेगा, – tttony

2

मैं भारी उठाने और पाठ को पार्स करने के लिए Regex का उपयोग नहीं करता।

var data = @"  JOINTS    DISPL.-X    DISPL.-Y    ROTATION 


     1   0.000000E+00   0.975415E+01   0.616921E+01 
     2   0.000000E+00   0.000000E+00   0.000000E+00"; 

var lines = data.Split('\r', '\n').Where(s => !string.IsNullOrWhiteSpace(s)); 
var regex = new Regex(@"(\S+)"); 

var dataItems = lines.Select(s => regex.Matches(s)).Select(m => m.Cast<Match>().Select(c => c.Value)); 

enter image description here

+0

मुझे लगता है कि मैं इस दृष्टिकोण के साथ जा सकता हूं, लेकिन कम लिंक का उपयोग कर रहा हूं, क्योंकि मुझे कोड बनाए रखना है और आपको देखना है, मुझे नहीं पता कि क्या हो रहा है ... – ian93

+3

शायद लिंक सीखना चाहें यह वास्तव में शक्तिशाली है। आखिरी पंक्तियां प्रत्येक पंक्ति से मेल खाती हैं और एक जगह नहीं है जो सब कुछ खींचती है और फिर 'MatchCollection' के अंदर 'कैप्चर कोलेक्शन' से मान निकालती है। – Romoku

+5

मैं मानता हूं, यह थोडा मजाकिया है जब रेगेक्स स्टेटमेंट का उपयोग करने वाला कोई व्यक्ति जटिल दिखने के लिए एक लिनक स्टेटमेंट को खारिज कर देता है। संक्षेप में शक्ति है, यह linq के साथ ही regexes पर लागू होता है। –

1

क्यों न सिर्फ मान कैप्चर और बाकी की उपेक्षा। यहां एक रेगेक्स है जो मान प्राप्त करता है।

string data = @"JOINTS DISPL.-X DISPL.-Y ROTATION 
1 0.000000E+00 0.975415E+01 0.616921E+01 
2 0.000000E+00 0.000000E+00 0.000000E+00"; 

string pattern = @"^ 
\s+ 
(?<Joint>\d+) 
\s+ 
(?<ValX>[^\s]+) 
\s+ 
(?<ValY>[^\s]+) 
\s+ 
(?<Rotation>[^\s]+)"; 

var result = Regex.Matches(data, pattern, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture) 
        .OfType<Match>() 
        .Select (mt => new 
        { 
        Joint = mt.Groups["Joint"].Value, 
        ValX = mt.Groups["ValX"].Value, 
        ValY = mt.Groups["ValY"].Value, 
        Rotation = mt.Groups["Rotation"].Value, 
        }); 
/* result is 
IEnumerable<> (2 items) 
Joint ValX ValY Rotation 
1 0.000000E+00 0.975415E+01 0.616921E+01 
2 0.000000E+00 0.000000E+00 0.000000E+00 
*/ 
संबंधित मुद्दे