在所有比赛中通过 RegEx 替换单个组

Replace single group via RegEx in all matches

我有一个包含 HTML 元素的文本,其中超链接不包含 URL,而是包含超链接应打开的项目的 ID。现在我正在尝试获取所有这些 ID 并用新 ID 替换它们。场景是,所有 ID 都已更改,我有一个包含 "oldId -> newID" 的字典,需要在文本中替换它。

这个输入

Some text some text <a href = "##1234"> stuff stuff stuff <a href="##9999"> xxxx

有了这个字典映射

1234 -> 100025
9999 -> 100026

应该生成此输出

Some text some text <a href = "##100025"> stuff stuff stuff <a href="##100026"> xxxx

到目前为止我有这个:

var textContent = "...";

var regex = new Regex(@"<\s*a\s+href\s*=\s*""##(?<RefId>\d+)""\s*\?\s*>");
var matches = regex.Matches(textContent);

foreach (var match in matches.Cast<Match>())
{
    var id = -1;
    if (Int32.TryParse(match.Groups["RefId"].Value, out id))
    {
        int newId;
        // idDictionary contains the mapping from old id to new id
        if (idDictionary.TryGetValue(id, out newId))
        {
          // Now replace the id of the current match with the new id
        }
    }
}`

我现在如何更换 ID?

除非您也从 HTML 中提取新 ID,否则我不明白为什么您不能在此处直接使用 String.Replace

var html = "Some text some text <a href = '##1234'> stuff stuff stuff <a href='##9999'> xxxx";
var mappings = new Dictionary<string, string>() 
{
    { "1234", "100025" },
    { "9999", "100026" },
    ...
};
foreach (var map in mappings) 
{
    html = html.Replace("##" + map.Key, "##" + map.Value);
}

Fiddle

只需在替换中使用回调即可。

regex.Replace(textContent, delegate(Match m) {
    int id = -1, newId;
    if (Int32.TryParse(m.Groups["RefId"].Value, out id)) {
        if (idDictionary.TryGetValue(id, out newId))
            return newId.ToString();
    }
    return m.Value; // if TryGetValue fails, return the match
});

不要用正则表达式解析 HTML。

但是,如果您必须尝试执行替换,请使用 Replace 方法

var updatedContent =  regex.Replace(textContent, match =>
    {
        var id = -1;
        if (Int32.TryParse(match.Groups["RefId"].Value, out id))
        {
            int newId;
            // idDictionary contains the mapping from old id to new id
            if (idDictionary.TryGetValue(id, out newId))
            {
                // Now replace the id of the current match with the new id
                return newId.ToString();
            }
        }

        // No change
        return match.Value;
    });

编辑:正如您所指出的,这取代了整个匹配。哎呀

首先,更改您的正则表达式,以便您要替换的内容 整个匹配项:

@"(?<=<\s*a\s+href\s*=\s*""##)(?<RefId>\d+)(?=""\s*\?\s*>)"

这只匹配一串数字,但确保它前后都有 HTML 标记。

它现在应该做你想做的事,但为了整洁你可以用 \d+ 替换 (?<RefId>\d+) (因为你不再需要组了)和 match.Groups["RefId"].Value 与只是 match.Value.