【问题标题】:Regex: Named groups and replacements正则表达式:命名组和替换
【发布时间】:2009-07-08 17:24:23
【问题描述】:

有办法

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

最后一个参数支持${groupName}等模式替换(但我不知道运行时的组名)。

就我而言,我有动态创建的模式,例如:

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

我的目的是用取决于组名的值替换每个组。例如,单词“word1”将替换为&lt;span class="c0"&gt;word1&lt;/span&gt;。这适用于像 google 一样突出显示搜索结果。

是否可以使用上面的方法而不是使用带有MatchEvaluator参数的重载方法来做到这一点?

提前致谢!

【问题讨论】:

  • 我会选择 MatchEvaluator... 它有效...
  • 好的,谢谢!实际上,我有一个使用 MatchEvaluator 的工作解决方案。但是只有一行代码而不是六七行的解决方案会多么优雅:)

标签: c# .net regex


【解决方案1】:

我认为以您建议的方式使用 ${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);

输出:

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.

【讨论】:

  • 谢谢!我已经以这种方式解决了我的问题。但在“一行”一词下,我的意思是 Regex.Replace(string source, string pattern, "$&")。其中 ${groupName} 是一个神话般的组名替换(但它在组名已知时起作用;)。但在我的情况下似乎是不可能的。再次感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 2012-08-26
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多