问题 String.Format计算预期args的数量


是否可以计算字符串中预期的args / params的数量 String.Format()

例如: "Hello {0}. Bye {1}" 应该返回2的计数。

我需要在之前显示错误 string.Format() 抛出一个例外。

谢谢你的帮助。


4251
2018-02-14 05:29


起源

为什么不简单地捕获异常并显示错误呢? - Marcelo Cantos
可能重复 stackoverflow.com/questions/2156497/... - nybbler
我会采取另一种方法。但是你的问题的答案是你只需要解析字符串。您需要处理“{{0}}”之类的情况,这些情况不计算在内。您还需要处理“{0:#,## 0}”之类的情况。那是你的答案。再说一次,我不会采取这种方法。 - Jonathan Wood
“请不要问我为什么需要这样做”  - blogs.msdn.com/b/oldnewthing/archive/2006/03/23/558887.aspx - Ed S.
可能重复 有没有更好的方法来计算C#中字符串中的字符串格式占位符? - Joe


答案:


您可以使用正则表达式,如{(。*?)},然后只计算匹配。如果你需要处理像{0} {0}这样的情况(我想它应该返回1)那么这会让它变得有点困难,但是你总是可以把所有的匹配放在一个列表中,做一个Linq select distinct就可以了。我在想类似下面的代码:

var input = "{0} and {1} and {0} and {2:MM-dd-yyyy}";
var pattern = @"{(.*?)}";
var matches = Regex.Matches(input, pattern);
var totalMatchCount = matches.Count;
var uniqueMatchCount = matches.OfType<Match>().Select(m => m.Value).Distinct().Count();
Console.WriteLine("Total matches: {0}", totalMatchCount);
Console.WriteLine("Unique matches: {0}", uniqueMatchCount);

编辑:

我想解决评论中提出的一些问题。下面发布的更新代码处理存在转义括号序列的情况(即{{5}}),其中未指定参数,并且还返回最高参数+ 1的值。代码假定输入字符串将形成良好,但在某些情况下,这种权衡是可以接受的。例如,如果您知道输入字符串是在应用程序中定义的而不是由用户输入生成的,则可能不需要处理所有边缘情况。也可以使用单元测试来测试要生成的所有错误消息。我喜欢这个解决方案的是它最有可能处理抛出它的绝大多数字符串,并且它比一个识别的解决方案更简单。 这里 (这表明string.AppendFormat的重新实现)。我会解释这样的事实:这段代码可能无法通过使用try-catch处理所有边缘情况,只返回“无效的错误消息模板”或其他类似的东西。

下面代码的一个可能的改进是更新正则表达式而不返回前导“{”字符。这将消除对Replace(“{”,string.Empty)的需要。同样,这段代码在所有情况下可能并不理想,但我认为它充分解决了所提出的问题。

const string input = "{0} and {1} and {0} and {4} {{5}} and {{{6:MM-dd-yyyy}}} and {{{{7:#,##0}}}} and {{{{{8}}}}}";
//const string input = "no parameters";
const string pattern = @"(?<!\{)(?>\{\{)*\{\d(.*?)";
var matches = Regex.Matches(input, pattern);
var totalMatchCount = matches.Count;
var uniqueMatchCount = matches.OfType<Match>().Select(m => m.Value).Distinct().Count();
var parameterMatchCount = (uniqueMatchCount == 0) ? 0 : matches.OfType<Match>().Select(m => m.Value).Distinct().Select(m => int.Parse(m.Replace("{", string.Empty))).Max() + 1;
Console.WriteLine("Total matches: {0}", totalMatchCount);
Console.WriteLine("Unique matches: {0}", uniqueMatchCount);
Console.WriteLine("Parameter matches: {0}", parameterMatchCount);

12
2018-02-14 05:45



@Joe,那么有一个可以算不上的正则表达式。期望的参数? - Divi
@Joe,divi这将返回字符串“Somestuff {5}”的值为1 ...你不是对5感兴趣而不是1吗? - deepee1
@Deepee1 - Somestuff {5}应该返回值6而不是5.但是,它应该返回6。 - Divi
这有助于我从这里发布的一些链接获得一些帮助。谢谢 - Divi
@joe请看我的编辑,我试图解决你的问题。谢谢。 - rsbarro


我认为这将处理Escape括号和0:0000的东西...将给出最大的括号值...所以在我的例子中将给出1。

       //error prone to malformed brackets...
        string s = "Hello {0:C} Bye {1} {0} {{34}}";

        int param = -1;
        string[] vals = s.Replace("{{", "").Replace("}}", "").Split("{}".ToCharArray());
        for (int x = 1; x < vals.Length-1; x += 2)
        {
            int thisparam;
            if (Int32.TryParse(vals[x].Split(',')[0].Split(':')[0], out thisparam) && param < thisparam)
                param = thisparam;
        }
        //param will be set to the greatest param now.

3
2018-02-14 05:43



string.format甚至可以处理嵌套括号吗? - p.campbell
MessageBox.Show(String.Format(“yopa {{0}}”,“test”));输出“yopa {0}”,因此它确实处理了转义。我错过了嵌套,我的意思是逃避。 - deepee1
+1为您的帮助 - Divi
这比RegEx方法更精彩,更容易阅读。 - Anton Krouglov