2009-07-08 15 views
5

bir yöntem yokturRegex: Adlandırılmış gruplar ve değiştirmeler

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

son parametre (ama çalıştırma süresi içinde grup adını bilmiyorum) bu tür ${groupName} ve diğerleri gibi desen değiştirmeler destekler. Ben gibi dinamik olarak oluşturulan desen var Benim durumumda

:

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

Benim amaç değeri grup adı bağlı olan her gruba değiştirmektir. Örneğin, "word1" kelimesi <span class="c0">word1</span> ile değiştirilecektir. Bu, google gibi öne çıkan arama sonuçları içindir.

o MatchEvaluator parametresi ile aşırı yöntemiyle değil yukarıdaki yöntemi kullanarak bunu yapmak mümkün mü?

Şimdiden teşekkürler!

+0

Sadece MatchEvaluator gelirdim ... çalıştığını ... –

+0

Evet, teşekkürler! Aslında MatchEvaluator ile çalışan bir çözümüm var. Ama ne kadar zarif altı-yedi yerine sadece bir satır kod ile bir çözüm olurdu :) – Alex

cevap

3

Yapılmakta olan değiştirmeyi yanlış anlamış olmadıkça, $ {groupname} öğesini önerdiğiniz şekilde uygulanabilir olduğunu düşünmüyorum. Bunun nedeni, yedek dizenin her grup adı için hesaplanacak şekilde yapılması gerektiğidir. Dinamik olarak üretildiklerinden, bu mümkün olmaz. Diğer bir deyişle, 1 ifadesinde, c0 ... cn'yi kaplayacak ve ilgili yakalama değerlerini değiştirecek bir yedek dizge tasarlıyor musunuz? Adlar arasında geçiş yapabilirsiniz ancak grup adı başına 1 değişiklik yapmak için değiştirilen metni bozulmadan nasıl saklarsınız?

Sizin için olası bir çözümüm var. Halen MatchEvaluator aşırı yükünü kullanır, ancak bazı lambda ifadeleri ve LINQ ile bunu 1 çizgiye indirebilirsin. Ancak, aşağıda açıklık için biçimlendiririm. Belki bu sizin ihtiyaçlarınıza uyacak veya sizi doğru yönde gösterecektir.

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); 

Çıktı:

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

Teşekkür ederim! Sorunumu böyle bir şekilde çözdüm. Ancak "tek satır" terimi altında, Regex.Replace (dize kaynağı, dize kalıbı, " $ &") gibi bir şey ifade ettim. $ {GroupName} öğesinin efsanevi grup adı yerine geçtiği yer (ancak grup adı bilindiğinde çalışır;). Ama benim durumumda imkansız görünüyor. Cevap için bir daha teşekkürler! – Alex

İlgili konular