2009-07-08 3 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

Смежные вопросы