String.Format - 从格式字符串中查询元数据

时间:2017-02-16 11:28:40

标签: c#

是否有任何函数可以从格式字符串中查询预期的输入和格式 - 即一个用作String.Format函数的第一个参数?

e.g。给出:

"On {0:yyyyy-MM-dd} do {1} and earn {2:C2}"

我希望得到类似的内容:

{"yyyyy-MM-dd", null, "C2"}

我认为正则表达式是一种可能性,但是有什么预先设定与String.Format挂钩的逻辑吗?

2 个答案:

答案 0 :(得分:1)

String.Format本身并不解析格式字符串。它最终调用内部StringBuilder.AppendFormatHelper方法,该方法仅将格式字符串视为分隔字符串。它并没有尝试解析它们。格式直接传递给每个参数类型的格式化方法。对于运行时和应用程序,字符串格式化性能至关重要。

您可以使用正则表达式来解析格式字符串。您需要处理转义大括号({{,{})和对齐字符串。

正则表达式{(?<index>\d+)(,(?<algn>-?\d+?))?(:(?<fmt>.*?))?}将索引,对齐和格式段提取为命名组。它没有明确地处理转义的大括号*。它将避免{{ {}但不会{{2,20:N{}

var regex=new System.Text.RegularExpressions.Regex(@"{(?<index>\d+)(,(?<algn>-?\d+?))?(:(?<fmt>.*?))?}");
var matches=regex.Matches("asdf{0:d2} {1:yyyy-MM-dd} {2,-20:N2}");
foreach(Match match in matches)
{
    Console.WriteLine("{0,-5} {1,-15} {2,-15}",
                       match.Groups["index"].Value, 
                       match.Groups["algn"].Value,
                       match.Groups["fmt"].Value);
}

这将返回:

0                d2             
1                yyyy-MM-dd     
2     -20        N2             

(?<name>...)语法捕获模式并将其公开为命名组。 (?<index>\d+)捕获一系列数字并将其公开为组index

?中的.*?指定非贪婪匹配。通常,正则表达式是贪婪的 - 它将捕获尽可能多的字符匹配模式。通过使用.*?,正则表达式将在下一个模式开始之前捕获尽可能少的字符。这就是可选的algn组在:停止的原因。

答案 1 :(得分:0)

机会不是标准的手段。使用Regex,很简单:

var args = new List<string>();
var str = "On {0:yyyyy-MM-dd} do {1} and earn {2:C2}";
MatchCollection matches = Regex.Matches(str, @"\{\d+[^\{\}]*\}");
foreach (Match match in matches)
{
  string obj = null;
  var split = match.ToString().Split(':');
  if (split.Length == 2) obj = split.Last().Trim(' ', '}', '{');
  args.Add(obj);
}

// Result: args = {"yyyyy-MM-dd", null, "C2"}