2009-07-08 14 views
5

वहाँ एक विधिRegex: नाम समूहों और प्रतिस्थापन

Regex.Replace(string source, string pattern, string replacement) 

पिछले पैरामीटर ऐसे ${groupName} और दूसरों के रूप में पैटर्न प्रतिस्थापन का समर्थन करता है (लेकिन मैं चलाने के समय में समूह का नाम पता नहीं है)।

मेरे मामले में मेरे पास है जैसे डायनामिक रूप से तैयार पैटर्न:

(?<c0>word1)|(?<c1>word2)|(?<c2>word3) 

मेरे उद्देश्य मूल्य समूह नाम के आधार पर प्रत्येक समूह को बदलने के लिए है। उदाहरण के लिए, "word1" शब्द को <span class="c0">word1</span> से बदल दिया जाएगा। यह Google की तरह हाइलाइट करने वाले खोज परिणामों के लिए है।

क्या MatchEvaluator पैरामीटर के साथ ओवरलोडेड विधि का उपयोग न करने के ऊपर उपरोक्त विधि का उपयोग करना संभव है?

अग्रिम धन्यवाद!

+0

मैं सिर्फ MatchEvaluator साथ जाना चाहते हैं ... यह काम करता है ... –

+0

हाँ, धन्यवाद! असल में मेरे पास MatchEvaluator के साथ एक कामकाजी समाधान है। लेकिन छह-सात के बजाय कोड की केवल एक पंक्ति के साथ समाधान कितना सुरुचिपूर्ण होगा :) – Alex

उत्तर

3

मुझे लगता है कि आपके द्वारा सुझाए गए तरीके से $ {groupname} का उपयोग करने के बारे में नहीं लगता है जब तक कि मैं निष्पादित होने वाले सटीक प्रतिस्थापन को गलत समझ नहीं पा रहा हूं। इसका कारण यह है कि प्रतिस्थापन स्ट्रिंग का निर्माण इस तरह से किया जाना चाहिए कि यह प्रत्येक समूह के नाम के लिए जिम्मेदार है। चूंकि वे गतिशील रूप से जेनरेट किए जाते हैं, इससे यह संभव नहीं होता है। दूसरे शब्दों में, कैसे, 1 कथन में, क्या आप एक प्रतिस्थापन स्ट्रिंग तैयार करते हैं जो c0 ... cn को कवर करेगा और उनके संबंधित कैप्चर मानों को प्रतिस्थापित करेगा? आप नामों के माध्यम से लूप कर सकते हैं लेकिन प्रति समूह नाम 1 प्रतिस्थापन करने के लिए आप संशोधित पाठ को कैसे बरकरार रखेंगे?

हालांकि मेरे पास आपके लिए एक संभावित समाधान है। यह अभी भी MatchEvaluator अधिभार का उपयोग करता है, लेकिन कुछ लैम्ब्डा अभिव्यक्तियों और LINQ के साथ आप इसे 1 पंक्ति तक प्राप्त कर सकते हैं। हालांकि, मैं इसे स्पष्टता के लिए प्रारूपित कर दूंगा। शायद यह आपकी जरूरतों को पूरा करेगा या आपको सही दिशा में इंगित करेगा।

string text = @"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog."; 
string[] searchKeywords = { "quick", "fox", "lazy" }; 

// build pattern based on keywords - you probably had a routine in place for this 
var patternQuery = searchKeywords 
         .Select((s, i) => 
          String.Format("(?<c{0}>{1})", i, s) + 
          (i < searchKeywords.Length - 1 ? "|" : "")) 
         .Distinct(); 
string pattern = String.Join("", patternQuery.ToArray()); 
Console.WriteLine("Dynamic pattern: {0}\n", pattern); 

// use RegexOptions.IgnoreCase for case-insensitve search 
Regex rx = new Regex(pattern); 

// Notes: 
// - Skip(1): used to ignore first groupname of 0 (entire match) 
// - The idea is to use the groupname and its corresponding match. The Where 
// clause matches the pair up correctly based on the current match value 
// and returns the appropriate groupname 
string result = rx.Replace(text, m => String.Format(@"<span class=""{0}"">{1}</span>", 
        rx.GetGroupNames() 
        .Skip(1) 
        .Where(g => m.Value == m.Groups[rx.GroupNumberFromName(g)].Value) 
        .Single(), 
        m.Value)); 

Console.WriteLine("Original Text: {0}\n", text); 
Console.WriteLine("Result: {0}", result); 

आउटपुट:

Dynamic pattern: (?<c0>quick)|(?<c1>fox)|(?<c2>lazy) 

Original Text: The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 

Result: The <span class="c0">quick</span> brown <span class="c1">fox</span> jumps over the <span class="c2">lazy</span> dog. The <span class="c0">quick</span> brown <span class="c1">fox</span> jumps over the <span class="c2">lazy</span> dog. 
+0

धन्यवाद! मैंने अपनी समस्या को इस तरह हल किया है। लेकिन "एक पंक्ति" शब्द के तहत मेरा मतलब था Regex.Replace (स्ट्रिंग स्रोत, स्ट्रिंग पैटर्न, " $ और")। जहां $ {groupName} एक पौराणिक समूह नाम प्रतिस्थापन है (लेकिन यह तब काम करता है जब समूह का नाम ज्ञात होता है;)। लेकिन लगता है कि यह मेरे मामले में असंभव है। उत्तर के लिए एक और धन्यवाद! – Alex

संबंधित मुद्दे