2009-07-08 16 views
5

方法正規表現:名前付きグループや交換

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で動作するソリューションを持っています。しかし、どのようにエレガントなのは、6行7行ではなく、1行のコードでしか解決できないでしょう:) – 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

ありがとう!私はそのような方法で問題を解決しました。しかし、 "1行"という言葉の下で、私はRegex.Replace(文字列ソース、文字列パターン、 " $&")のようなものを意味しました。 $ {groupName}は神話的なグループ名の置き換えです(ただし、グループ名が分かっている場合は動作します)。しかし、私の場合は不可能だと思われる。 もう一度お返事ありがとうございます! – Alex

関連する問題