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

C# 模板占位符字典映射替换异常,无法生成正确文件头字符串

问题产生的核心原因
  • 字符串重复拼接:每次匹配到闭合的#分隔符时,代码调用str.Remove(i + 1)获取了从字符串开头到当前位置的全部内容,直接追加到结果串中,导致前面的内容被反复拼接,这是输出出现大量重复片段的根本原因。
  • 普通字符遗漏追加:不在#占位符范围内的普通字符,没有任何逻辑追加到结果串,最终输出会缺失大量非占位符内容。
  • 字典查询大小写不匹配:你存在headerCdataIndexKeyVals里的Key是大小写混合的,但查询时调用了headerSubstring.ToUpper(),除非你存Key的时候也统一转大写,否则根本匹配不到对应值。
  • 占位符截取逻辑错误:WSM分支的str.Remove(len + 1)截取长度完全错误,无法正确替换#WSM#占位符。
  • 未覆盖未匹配占位符的处理逻辑:你要求未匹配到Key的占位符替换为空,现有逻辑只追加了闭合分隔符,不会删除整个占位符。
修复后的栈实现代码
public static string FindSubsInDelimetersAndReturn(string str, char openDelimiter, char closeDelimiter, HeaderMapperData mapperData )
{
    StringBuilder newString = new StringBuilder();
    int lastAppendPos = 0;
    Stack<int> dels = new Stack<int>();
    for (int i = 0; i < str.Length; i++)
    {
        if (str[i] == openDelimiter && dels.Count == 0)
        {
            // 先追加占位符之前的普通字符
            newString.Append(str.Substring(lastAppendPos, i - lastAppendPos));
            dels.Push(i);
        }
        else if (str[i] == closeDelimiter && dels.Count > 0)
        {
            int openPos = dels.Pop();
            string placeholder = str.Substring(openPos + 1, i - openPos - 1);
            string replaceVal = string.Empty;
            
            // 处理匹配逻辑
            if (placeholder == "WSM" && closeDelimiter == '#')
            {
                replaceVal = "";
            }
            else if (mapperData.HeaderCdataIndexKeyVals.TryGetValue(placeholder.ToLower(), out int index))
            {
                string[] parts = placeholder.Split('.');
                if (parts.Length >= 2)
                {
                    string arrayKey = parts[1].ToLower();
                    if (placeholder.Contains("container.context", StringComparison.OrdinalIgnoreCase) && parts.Length >=3)
                    {
                        arrayKey = $"{parts[1].ToLower()}.{parts[2].ToLower()}";
                    }
                    if (mapperData.HeaderCdataArrayKeyVals.TryGetValue(arrayKey, out List<string> valList) && index < valList.Count)
                    {
                        replaceVal = valList[index];
                    }
                }
            }
            // 追加替换后的值
            newString.Append(replaceVal);
            lastAppendPos = i + 1;
        }
    }
    // 追加最后一个占位符后的剩余字符
    newString.Append(str.Substring(lastAppendPos));
    return newString.ToString();
}

使用前请先把headerCdataIndexKeyVals的所有Key统一转成小写存储,和查询逻辑对齐。

更简洁的实现方式

因为你的占位符是#包裹且不存在嵌套场景,完全不需要用栈处理,直接用正则匹配替换即可,逻辑更简洁不易出错:

using System.Text.RegularExpressions;

// 预编译正则匹配所有#包裹的占位符
private static readonly Regex PlaceholderRegex = new Regex(@"#([^#]+)#", RegexOptions.Compiled);

public static string ReplaceHeaderPlaceholders(string str, HeaderMapperData mapperData)
{
    return PlaceholderRegex.Replace(str, match =>
    {
        string placeholder = match.Groups[1].Value;
        if (placeholder == "WSM")
        {
            return "";
        }
        if (!mapperData.HeaderCdataIndexKeyVals.TryGetValue(placeholder.ToLower(), out int index))
        {
            return "";
        }
        string[] parts = placeholder.Split('.');
        if (parts.Length < 2)
        {
            return "";
        }
        string arrayKey = parts[1].ToLower();
        if (placeholder.Contains("container.context", StringComparison.OrdinalIgnoreCase) && parts.Length >=3)
        {
            arrayKey = $"{parts[1].ToLower()}.{parts[2].ToLower()}";
        }
        if (mapperData.HeaderCdataArrayKeyVals.TryGetValue(arrayKey, out List<string> valList) && index < valList.Count)
        {
            return valList[index];
        }
        return "";
    });
}

该实现逐行处理时仅对当前行做一次正则匹配,不会产生全量文件解析的性能损耗,同时满足占位符无匹配时返回空的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:36:02