How to replace {vars} in a string?

I have a string

string str = "Bem vindo {Usuario}. Agora são: {Horas}";

I want to replace {Usuario} with a name and {Horas} with the current time, how can I do that?

Author: Maniero, 2013-12-19

4 answers

One idea is to use a IFormattable that understands its formats. For example, if you have a class like this:

class Modelo : IFormattable {
  public string Usuario { get; set; }
  public DateTime Horas { get { return DateTime.Now; } }
  public string ToString(string format, IFormatProvider formatProvider) {
    if (format == "Usuario") return Usuario;
    if (format == "Horas") return Horas.ToString();
    throw new NotSupportedException();
  }
}

You can use it this way:

var modelo = new Modelo { Usuario = "Lobo" };
var strFinal = string.Format("Bem vindo {0:Usuario}. Agora são: {0:Horas}", modelo);

Note that you still need to use the index of the object that will make the substitution (in this case, 0).

You can implement IFormattable using Reflection, for example, to override any property of the object.

 6
Author: Jordão, 2013-12-20 01:33:20

C# already has a function for this, it is called String.Format see documentation .

String.Format("Bem vindo {0}. Agora são: {1}", usuario, hora);

However if you want to implement something similar, you can use Regex as follows

var result = Regex.Replace(str, @"{(?<Parametro>[^}]+)}", m =>
{
    string variavel = m.Groups["Parametro"].Value; // Usuario, Horas
    switch (variavel)
    {
        case "Usuario": return usuario;
        case "Horas": return hora;
    }
    return "";
});

The syntax (?<SomeName>.*) means that this is a named group, see the documentation here.

This allows you to access specific captured groups, through match.Groups["NomeDoGrupo"].Value.

This way you can capture the tokens and replace them as want.

Although this mode is possible, I suggest using String.Format which has been well thought out, validated and is the default for this type of operation.

 7
Author: BrunoLM, 2013-12-19 02:16:43

As a complement to everything that was answered in C # 6 there is a new interpolation feature of string in which, depending on the goal, it is possible to put all this aside and let the language/Framework Take care of this for you. Then using:

string str = $"Bem vindo {Usuario}. Agora são: {Horas}"

Will already achieve the desired result provided that at the time of evaluation of the string you have the variables Usuario and Horas in the scope.

Read more on the subject .

 7
Author: Maniero, 2017-04-13 12:59:43

If your key "{Usuario} " is fixed, it may be better to simply make a text substitution instead of using regular expressions. Thes are very nice and powerful, but there is a certain computational cost to pay.

With a very simple test using the suggestion of ER offered by @BrunoLM (which incidentally, was a very nice suggestion), you can see that the difference in processing time is quite considerable:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        static string replace1(string str)
        {
            var result = Regex.Replace(str, @"{(?<Parametro>[^}]+)}", m =>
            {
                string variavel = m.Groups["Parametro"].Value; // Usuario, Horas
                switch (variavel)
                {
                    case "Usuario": return "Fulano da Silva";
                    case "Horas": return DateTime.Now.ToString("HH:mm:ss tt");
                }
                return "";
            });
            return result;
        }

        static string replace2(string str)
        {
            str = str.Replace("{Usuario}", "Beltrano da Silva");
            str = str.Replace("{Horas}", DateTime.Now.ToString("HH:mm:ss tt"));
            return str;
        }

        static void Main(string[] args)
        {

            string str = "Bem vindo {Usuario}. Agora são: {Horas}";

            DateTime dStart = DateTime.Now;
            Console.Out.WriteLine("Resultado 1: " + Program.replace1(str));
            DateTime dEnd = DateTime.Now;
            Console.Out.WriteLine("Duração: " + (dEnd - dStart).TotalMilliseconds);

            dStart = DateTime.Now;
            Console.Out.WriteLine("Resultado 2: " + Program.replace2(str));
            dEnd = DateTime.Now;
            Console.Out.WriteLine("Duração: " + (dEnd - dStart).TotalMilliseconds);
        }
    }
}

Produces the following output (duration in milliseconds):

Resultado 1: Bem vindo Fulano da Silva. Agora são: 15:28:15
Duração: 9,0005
Resultado 2: Bem vindo Beltrano da Silva. Agora são: 15:28:15
Duração: 1
 3
Author: Luiz Vieira, 2013-12-19 17:31:42