C# - 在 string.Format 中自动检测转义和参数大括号

C# - Auto-detect Escape and Argument curly braces in string.Format

从此 C# 示例开始:

string myStringFormat = "I want to surround string {0} with {{ and }}";
string myStringArgs = "StringToSurround";
string myFinalString = string.Format(myStringFormat, myStringArgs);

我想知道是否有一种快速简单的方法来区分转义 character/sequence 和 curly braces/brackets 的参数。

我问这个问题的原因是:
+] 我想提供一些日志记录功能,我不想要求用户知道双卷曲 braces/brackets 转义规则
+] 我想快速区分性能需求

目前我能想到的唯一解决方案是扫描字符串寻找卷曲 braces/brackets 并对后续字符进行一些检查(数字解析)。正则表达式可能会有帮助,但我找不到在这种情况下使用它们的方法。

顺便说一句,我想要实现的最终情况是允许用户执行此操作而不会出现异常:

string myStringFormat = "I want to surround string {0} with { and }";
string myStringArgs = "StringToSurround";
//string myFinalString = string.Format(myStringFormat, myStringArgs); throwing exception
string myFinalString = MyCustomizedStringFormat(myStringFormat, myStringArgs);

编辑:

抱歉 "surround" 这个词很狡猾且具有误导性,请考虑这个例子:

string myStringFormat = "I want to append to string {0} these characters {{ and }}";
string myStringArgs = "StringToAppendTo";
string myFinalString = string.Format(myStringFormat, myStringArgs);

给出输出
我想追加到字符串 StringToAppendTo 这些字符 { 和 }

使用此正则表达式查找参数子字符串:

{\d+}

这个正则表达式转义{}{1a}等,只选择{1}{11}


现在您需要处理 Arguments(用它们的值替换它们)或 Escaped 花括号(用双括号替换它们)。选择是你的,它取决于每个案例的出现次数。 (我选择替换下面代码中的参数)

现在您需要实际替换字符。同样,您可以选择是否使用 StringBuilder。这取决于您输入的大小和替换的数量。无论如何我建议 StringBuilder.

var m = Regex.Matches(input, @"{\d+}");
if (m.Any())
{
    // before any arg
    var sb = new StringBuilder(input.Substring(0, m[0].Index));

    for (int i = 0; i < m.Count; i++)
    {
        // arg itself
        sb.Append(args[i]);

        // from right after arg 
        int start = m[i].Index + m[i].Value.Length;

        if (i < m.Count - 1)
        {
            // until next arg
            int length = m[i + 1].Index - start;
            sb.Append(input.Substring(start, length));
        }
        else
            // until end of input
            sb.Append(input.Substring(start));
    }
}

我相信这是最健壮和最干净的方法,而且它没有任何性能(内存或速度)问题。


编辑

如果您无权访问 args[] 那么您可以先将 {/} 替换为 {{/}} 然后简单地执行对代码的这些修改:

  1. 使用此模式:@"{{\d+}}"
  2. m[i].Value.Substring(1, m[i].Value.Length - 2)而不是args[i]