C# Regex 更改每个匹配项的替换字符串

标签 c# regex

我有这样一个字符串:

string s = "<p>Hello world, hello world</p>";
string[] terms = new string[] {"hello", "world"};

我想在这个字符串上做一个替换,这样每个单词(不区分大小写)都将被匹配,并用一个带编号的索引跨度标签替换,如下所示:

<p>
    <span id="m_1">Hello</span> 
    <span id="m_2">world</span>, 
    <span id="m_3">hello</span> 
    <span id="m_4">world</span>!
</p>

我试过这样做。

int match = 1;
Regex.Replace(s,
    String.Join("|", String.Join("|", terms.OrderByDescending(s => s.Length)
        .Select(Regex.Escape))),
    String.Format("<span id=\"m_{0}\">$&</span>", match++),
    RegexOptions.IgnoreCase);

输出是这样的:

<p>
    <span id="m_1">Hello</span> 
    <span id="m_1">world</span>, 
    <span id="m_1">hello</span> 
    <span id="m_1">world</span>!
</p>

所有 id 都相同 (m_1),因为正则表达式不会为每个匹配项评估 match++,而是为整个正则表达式评估一个。我该如何解决这个问题?

最佳答案

您需要做的就是将替换参数从字符串模式转换为匹配评估器 (m => String.Format("<span id=\"m_{0}\">{1}</span>", match++, m.Value)):

string s1 = "<p>Hello world, hello world</p>";
string[] terms = new string[] {"hello", "world"};
var match = 1;
s1 = Regex.Replace(s1,
        String.Join("|", String.Join("|", terms.OrderByDescending(s => s.Length)
            .Select(Regex.Escape))),
    m => String.Format("<span id=\"m_{0}\">{1}</span>", match++, m.Value),
    RegexOptions.IgnoreCase);
Console.Write(s1);
// => <p><span id="m_1">Hello</span> <span id="m_2">world</span>, <span id="m_3">hello</span> <span id="m_4">world</span></p>

参见 C# demo

关于C# Regex 更改每个匹配项的替换字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43455680/

相关文章:

c# - 没有 Stream.ReadByteAsync?

c# - 如何在不同线程中使用 Entity Framework ?

javascript - 用于匹配有效 JavaScript 命名空间的正则表达式

php - 在换行符中使用 preg_match_all

php - 避免在 php 的 preg_replace 中进行反向引用替换

ios - swift 正则表达式格式?

c# - 在 C# 中在运行时构造一个函数

c# - 如何使用 .NET 5 的 IdentityModel 扩展生成 JWT token

c# - 我想要 "clone"谷歌日历与 c# .net 的接口(interface)

javascript - 使用正则表达式从 url 匹配 id