You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C# .NET替换Word文档中含换行的{{}}包裹文本?

C#替换Word中{{}}包裹文本失败的解决办法

问题场景

Word文档中有如下内容:

This is a test
{{3.3 iwanttochangethis}}

使用OpenXML SDK读取时,目标文本被拆分成多个独立的<w:t>节点,内容变成:

This is a test
{{
3.3
i
want
to
change
this
}}

原代码直接遍历单个<w:t>节点,只能匹配未被拆分的文本,尝试换行替换、正则匹配均无效。

问题根源

Word的OpenXML格式会根据排版规则(自动换行、格式变化等)将连续文本分割为多个<w:t>节点,每个节点对应一小段文本。直接处理单个节点无法匹配跨节点的完整{{}}包裹内容。

解决方案

方法一:合并相邻文本节点后替换

先将同一段落内的相邻文本节点合并,确保完整的{{}}内容在同一个<w:t>节点中,再进行正则替换,适合需要保留原格式的场景:

using (WordprocessingDocument doc = WordprocessingDocument.Open(outputPath, true))
{
    var body = doc.MainDocumentPart.Document.Body;

    // 遍历所有段落,合并相邻Run的Text内容
    foreach (var para in body.Descendants<Paragraph>())
    {
        var runs = para.Descendants<Run>().ToList();
        // 从后往前合并,避免索引错乱
        for (int i = runs.Count - 1; i > 0; i--)
        {
            var currentRun = runs[i];
            var prevRun = runs[i - 1];
            
            var currentText = currentRun.Descendants<Text>().FirstOrDefault();
            var prevText = prevRun.Descendants<Text>().FirstOrDefault();
            
            if (currentText != null && prevText != null)
            {
                prevText.Text += currentText.Text;
                currentRun.Remove();
            }
        }
    }

    // 正则替换所有{{}}包裹的内容
    foreach (var textNode in body.Descendants<Text>())
    {
        textNode.Text = Regex.Replace(textNode.Text, @"\{\{([\s\S]*?)\}\}", match =>
        {
            // 根据捕获的内容自定义替换逻辑
            var innerContent = match.Groups[1].Value.Trim();
            if (innerContent.StartsWith("3.3"))
            {
                return "To this";
            }
            // 其他内容保留原格式
            return match.Value;
        });
    }

    doc.MainDocumentPart.Document.Save();
}

方法二:按段落拼接文本后重新生成节点

直接拼接段落内所有文本内容,替换后重新生成节点,操作简单但会丢失段落内的局部格式,适合无需保留格式的场景:

using System.Text.RegularExpressions;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

// ...

using (WordprocessingDocument doc = WordprocessingDocument.Open(outputPath, true))
{
    var body = doc.MainDocumentPart.Document.Body;

    foreach (var para in body.Descendants<Paragraph>().ToList())
    {
        // 拼接段落内所有文本
        string fullParaText = string.Join("", para.Descendants<Text>().Select(t => t.Text));
        
        // 执行替换
        string replacedText = Regex.Replace(fullParaText, @"\{\{([\s\S]*?)\}\}", match =>
        {
            if (match.Groups[1].Value.Contains("3.3 iwanttochangethis"))
            {
                return "To this";
            }
            return match.Value;
        });

        // 清空原段落内容,添加新文本
        para.RemoveAllChildren<Run>();
        para.Append(new Run(new Text(replacedText)));
    }

    doc.MainDocumentPart.Document.Save();
}

注意事项

  • 方法一中,若段落内存在格式差异(如部分文本加粗),合并后会丢失局部格式,需根据实际场景调整合并逻辑;
  • 正则表达式@"\{\{([\s\S]*?)\}\}"中的[\s\S]可以匹配包括换行在内的任意字符,确保能匹配跨换行的{{}}内容;
  • 操作完成后务必调用Save()方法保存文档修改。

内容的提问来源于stack exchange,提问作者Nopidity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:24:56