Есть ли аналог preg_replace в c#?

203
03 августа 2018, 16:00

Есть массив "шаблонных слов". Можно ли прочитав шаблон(pattern) с БД сделать автозамену "шаблонных слов" на нужные. Например

"Здраствуйте %client%. Ваш заказ %order% будет доставлен %date%".

Ну если есть массив Dictionary<string,string> например, или если два массива - что заменять, и на что заменять. Т.е. встроеный шаблонизатор.

Или... хотя бы... делать это через Regex или есть более короткое рашение.

Answer 1

Странно, что никто в итоге не предложил вариант на регекспах, он, вроде, не сложен:

var template = "Здравствуйте, %client%! Ваш заказ %order% будет доставлен %date%.";
var pattern = "%.*?%";
var dict = new Dictionary<string, string>
{
    ["%client%"] = "Иван Иванович",
    ["%order%"] = "№007",
    ["%date%"] = "сегодня"
};
string evaluator(Match match) => dict.TryGetValue(match.Value, out var replacement) ? replacement : "n/a";
var result = Regex.Replace(template, pattern, evaluator);
Console.WriteLine(result);

Если не хотите держать в словаре все эти %, можно искать не match.Value, а match.Value.Trim('%')

Answer 2

Простой пример

var pattern = "%1% - %2% - %3%";
var dict = new Dictionary<string, string>() {{"%1%","odin"}, {"%2%","dwa"}, {"%3%","tri"}};
var res = dict.Aggregate(pattern, (acc, p)=>acc.Replace(p.Key, p.Value));
Console.WriteLine(res); 

Вывод

odin - dwa - tri
Answer 3

Раз пошла такая пьянка, добавлю немного мракобесия

public string Format<T>(string source, T data)
{
    var res = source;
    foreach (var p in typeof(T).GetProperties())
        res = res.Replace($"%{p.Name}%", p.GetValue(data)?.ToString()); 
    return res;
}
var pattern = "%name% - %date% - %age%";
Console.WriteLine(Format(pattern, new {name = "vasya", date = DateTime.Now, age = 18}));

Вывод

vasya - 25-Jun-18 16:06:20 - 18
Answer 4

Самый простой способ - string.Format:

var template = "Здравствуйте {0}. Ваш заказ {1} будет доставлен {2:dd.MM.yyyy}";
string.Format(template, "Вася", "фиговина", DateTime.Today);

При желании несложно сделать и выбор параметров по именам:

var template = "Здравствуйте {0:client}. Ваш заказ {0:order} будет доставлен {0:date:dd.MM.yyyy}";
string.Format(template, new CompositeFormattable(new
{
    client = "Вася",
    order = "фиговина",
    date = DateTime.Today,
}));
// ...
class CompositeFormattable : IFormattable
{
    private readonly object obj;
    public CompositeFormattable(object obj)
    {
        this.obj = obj;
    }
    public string ToString(string format, IFormatProvider provider)
    {
        var index = format.IndexOf(':');
        string propname;
        if (index >= 0)
        {
            propname = format.Substring(0, index);
            format = format.Substring(index + 1);
        }
        else
        {
            propname = format;
            format = null;
        }
        var value = obj.GetType().GetProperty(propname).GetValue(obj);
        if (value == null)
            return null;
        var formattableValue = value as IFormattable;
        if (formattableValue != null)
            return formattableValue.ToString(format, provider);
        else
            return value.ToString();
    }
}

Вариант через регулярки также возможен (метод Regex.Replace).

Answer 5

У меня получилось так, хотя, может быть, не самым оптимальным образом

string textInput = "Здраствуйте %client%. Ваш заказ %order% будет доставлен %date%";
Dictionary<string, string> masks = new Dictionary<string, string>
{
    { "%client%", "Иванов" },
    { "%order%", "Заказ №123" },
    { "%date%", "2 апреля 23:05" },
};
var query = (from s in textInput.Split(' ')
             from m in masks
             select s.Replace(m.Key, m.Value) into r
             where !r.StartsWith("%")
             select r).Distinct();

string result = String.Join(" ", query);
READ ALSO
NAudio - передача и воспроизведение mp3Frame через TCP

NAudio - передача и воспроизведение mp3Frame через TCP

Я пишу TCP сервер-клиент приложение, часть которого которое реализует воспроизведение выбранного серверомmp3 файла на всех подключённых клиентах

159
Semaphore в TPL

Semaphore в TPL

В моей программе доступ к функции должно иметь только определенное количество потоковЕсть следующий код:

202
Key Hook не определяет 4 кнопки сразу

Key Hook не определяет 4 кнопки сразу

Хочу выводить нажатые клавиши пользователем, в том числе сочетанияПробовал разные Key Lisener/Hook (они работают по одному и тому же принципу), но везде...

195
Обойти дерево в глубину

Обойти дерево в глубину

Есть такой набор данных:

205