【问题标题】:C# - Auto-detect Escape and Argument curly braces in string.FormatC# - 在 string.Format 中自动检测转义和参数花括号
【发布时间】:2020-01-23 15:10:23
【问题描述】:

从这个 C# 示例开始:

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

我想知道是否有一种快速简单的方法来区分转义字符/序列和花括号/方括号的参数。

我问这个的原因是:
+] 我想提供一些日志记录功能,我不想要求用户了解双花括号/方括号转义规则
+] 我想在性能要求上做这个区分的速度非常快

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

顺便说一句,我想达到的最终情况是允许用户这样做而不会出现异常:

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);

编辑:

抱歉,“环绕”一词很棘手且具有误导性,请考虑以下示例:

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

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

【问题讨论】:

  • string myStringFormat = "I want to surround string {{{0}}} with { and }"; - 三重 {{{..}}}。这里{{ 代表普通{,最后一个{ 代表字符串插值/格式化。
  • 必须是{} 吗?如果您选择另一个不太可能出现的标识符(如[[]]),您可以在将其交给您的字符串格式之前运行string.Replace
  • 让我直截了当:您希望用户编写 {0} 和 {a},但只有 {0} 应该被转换?
  • Bizhan,是的,你是对的。
  • 使用另一个字符

标签: c# string formatting escaping


【解决方案1】:

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

{\d+}

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


现在您需要处理参数(用它们的值替换它们)或转义花括号(用双括号替换它们)。选择是您的,这取决于每种情况的出现次数。 (我选择在下面的代码中替换参数)

现在您需要实际替换字符。同样,您可以选择是否使用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]

【讨论】:

  • 我已经尝试过你的代码,但我没有得到预期的结果:string input = "I want to append to string {0} these characters { and }"; string[] args = new string[1] { "StringToAppendTo" }; string result = ""; + 你的代码 + result = sb.ToString(); 输出是 StringToAppendTo 但是预期是 我想附加到字符串 StringToAppendTo 这些字符 { 和 }
  • @GiacomoPirinoli 非常抱歉!我修复了它现在工作的正则表达式模式。
猜你喜欢
  • 2011-12-29
  • 2016-01-13
  • 2016-07-08
  • 2011-04-15
  • 2015-11-23
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多