正则表达式:命名组和替换

Ale*_*lex 5 .net c# regex

有一种方法

Regex.Replace(string source, string pattern, string replacement)
Run Code Online (Sandbox Code Playgroud)

最后一个参数支持模式替换,例如${groupName}和其他参数(但我不知道运行时中的组名).

在我的情况下,我有动态创建的模式,如:

(?<c0>word1)|(?<c1>word2)|(?<c2>word3)
Run Code Online (Sandbox Code Playgroud)

我的目的是使用取决于组名的值替换每个组.例如,单词"word1"将替换为<span class="c0">word1</span>.这是针对像谷歌一样突出显示的搜索结果.

是否可以使用上述方法不使用带MatchEvaluator参数的重载方法来执行此操作?

提前致谢!

Ahm*_*eed 3

我认为按照您建议的方式使用 ${groupname} 是不可行的,除非我误解了正在执行的确切替换。原因是替换字符串的构造方式必须能够解释每个组名称。由于它们是动态生成的,因此这是不可能的。换句话说,在 1 条语句中,如何设计一个替换字符串来覆盖 c0...cn 并替换它们各自的捕获值?您可以循环遍历名称,但如何保持修改后的文本完整以对每个组名执行 1 次替换?

不过,我确实为你提供了一个可能的解决方案。它仍然使用 MatchEvaluator 重载,但使用一些 lambda 表达式和 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);
Run Code Online (Sandbox Code Playgroud)

输出:

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.
Run Code Online (Sandbox Code Playgroud)