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

use*_*285 5 c# regex

我有一个像这样的字符串:

string s = "<p>Hello world, hello world</p>";
string[] terms = new string[] {"hello", "world"};
Run Code Online (Sandbox Code Playgroud)

我想对此字符串进行替换,以便匹配每个单词(不区分大小写),并替换为带编号的索引span标记,如下所示:

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

我试着这样做.

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

输出是这样的:

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

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

Wik*_*żew 5

您需要做的就是将替换参数从字符串模式转换为匹配评估器(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>
Run Code Online (Sandbox Code Playgroud)

请参阅C#演示