Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Advanced Text-Replace with Regex.Matchevaluator

0.00/5 (No votes)
23 Jul 2016 1  
This is an alternative for C# Sprintf-Lite

Introduction

Let me demonstrate a powerful, but quite unknown overload of Regex.Replace().
I won't go into Regex-Programming in Detail - hopefully you are familiar with that, or you'll find a good Resource on the Internet.

The demand is - as stated here - to convert format-strings for the C-sprintf(format, <arglist>) - Function to format-strings, which are applicable to  the .NET- string.Format(format, <arglist>)-Function.

For instance, the C formatstring:

"%s shoots a %s at you for %d damage!"

is to convert to:

"{0} shoots a {1} at you for {2} damage!"

Code

  1  using System.Text.RegularExpressions;
  2  //...
  3  private static Regex _rgxPrint2Format = new Regex("%[sd]");
  4  
  5  private static string Sprint(string format,params object[] args) {
  6     var counter = 0;
  7     MatchEvaluator match2String = mt => string.Concat("{", counter++, "}");
  8     return string.Format(_rgxPrint2Format.Replace(format, match2String), args);
  9  }

You see: the problem is solved in 4 lines of code. To understand the solution, there is to understand, what a Matchevaluator is - see its definition in ObjectBrowser (<-follow the link, if you don't know the OB):

public delegate string MatchEvaluator(RegularExpressions.Match match)

It is a Delegate of a function, which converts a Regex.Match to a string.

In the code above, line#7, the function, targeted by the delegate is directly noted as anonymous Function within the same line, and it replaces the Match by "{<counter>}", then increments counter - that's all.
Next Line I pass my converter to _rgxPrint2Format.Replace(,) which applies it to each occurring match.
Means: The Regex finds the matches, the converter converts them to .NET-like placeholders, and therefore the .NET- string.Format() - method can apply the converted format-instructions to the args.

Code Usage

private void Test() {
   var output =  Sprint("%s %s", "hello", "World");
   Console.WriteLine(output);

   output = Sprint("%s", "hello", "World");
   Console.WriteLine(output);

   output = Sprint("%s %d", "hello", "World", 23);
   Console.WriteLine(output);

   output = Sprint("%s %s %d", "hello", "World", 23);

   Console.WriteLine(output);

   output = Sprint("%s shoots a %s at you for %d damage!", 
                   "lakedoo2310", "fireball", 99);
   Console.WriteLine(output);
}

The output is as expected:

hello World
hello
hello World
hello World 23
lakedoo2310 shoots a fireball at you for 99 damage!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here