Поиск и замена подстрок сопоставленными значениями

#c#

#c#

Вопрос:

Некоторые настройки хранятся в строке. Примером может быть

 string rawWatermarkFormat = "{@Charge}; {Current Date} {Current Time}; Scan Operator: {Scan Operator's User ID}; Page: x/y";
  

Каждая подстрока, заключенная в {…}, представляет собой ключ для словаря. Этот словарь содержит значение, которое необходимо заменить ключом. Конечная строка будет

 string parsedWatermarkFormat = "phosphoric acid; 24.04.2019 14:20; Scan Operator: 123; Page: x/y";
  

(да, текущая дата и текущее время также хранятся в этой коллекции)

Я хочу извлечь эти ключи, получить правильное значение из коллекции и заменить ключ значением. Я начал с этого

     public Parse()
    {
        string watermarkFormat = "{@Charge}; {Current Date} {Current Time}; Scan Operator: {Scan Operator's User ID}; Page: x/y"; // batch.get_CustomStorageString(Resources.WATERMARK_FORMAT_KEY);

        int currentFieldStart = 0;

        for (int i = 0; i < watermarkFormat.Length; i  )
        {
            char currentCharacter = watermarkFormat[i];

            if (currentCharacter == '{')
            {
                currentFieldStart = i;
            }
            else if (currentCharacter == '}')
            {
                int length = i - currentFieldStart;
                string currentField = watermarkFormat.Substring(currentFieldStart   1, length - 1);

                string fieldValue = "---"; // access the collection for the correct field value

                watermarkFormat = watermarkFormat
                    .Remove(currentFieldStart, length)
                    .Insert(currentFieldStart, fieldValue);
            }
        }
    }
  

Проблема в том, что если бы я заменил подстроку с помощью диапазонов, строка оборвалась бы. Если ключ имеет длину x, а значение имеет длину y, метод replace не будет работать для следующих полей.

Таким образом, эта watermarkFormat строка примера приведет к

---} {Current Time}; Scan Operator: ---}; Page: x/y

Как я могу правильно заменить поля?


Редактировать: rawWatermarkFormat это всего лишь пример строки! Я не знаю его длины, токенов и т.д. Таким образом, строка может быть также такой

 string rawWatermarkFormat = "{Current Date} {Current Date} {Current Date} {Current Date} {Current Date}"
  

или это

 string rawWatermarkFormat = "{blue car}"
  

Я должен извлечь эти строки и получить правильное значение из словаря. Я сам не знаю эти токены.

Комментарии:

1. строки .net неизменяемы.

2. может помочь регулярное выражение.

3. почему цикл и все такое? Почему вы не можете использовать замену строки или формат строки или интерполяцию строки?

4. Я думаю, вы, возможно, ищете токенизацию строк для решения вашей основной бизнес-проблемы. github.com/flipbit/tokenizer

5. Я обновил свой ответ

Ответ №1:

Используйте регулярное выражение в качестве альтернативы.

 string pattern = @"{[a-zA-Z-s@'] }";
string input = "{@Charge}; {Current Date} {Current Time}; Scan Operator: {Scan Operator's User ID}; Page: x/y";
var matches = System.Text.RegularExpressions.Regex.Matches(input, pattern);
foreach (var match in matches)
{
    Console.WriteLine(match);
    // TODO replace
    // var key = match.ToString();
    // input = input.Replace(key, someMethodToGetValue(key.Replace("{", "").Replace("}", "")));
}
  

Вывод на консоль:

 {@Charge}
{Current Date}
{Current Time}
{Scan Operator's User ID}
  

Ответ №2:

Это можно довольно легко решить с Regex.Replace помощью MatchEvaluator перегрузки делегата.

Вот пример LINQPad:

 void Main()
{
    string rawWatermarkFormat = "{@Charge}; {Current Date} {Current Time}; Scan Operator: {Scan Operator's User ID}; Page: x/y";
    Dictionary<string, string> keywordValues = new Dictionary<string, string>
    {
        ["@Charge"] = "phosphoric acid",
        ["Current Date"] = "24.04.2019",
        ["Current Time"] = "14:20",
        ["Scan Operator's User ID"] = "123",
    };

    Regex.Replace(rawWatermarkFormat, @"{(?<keyword>[^}] )}", me =>
    {
        if (keywordValues.TryGetValue(me.Groups["keyword"].Value, out string value))
            return value;
        return me.Value;
    }).Dump();
}
  

Это выводит:

 phosphoric acid; 24.04.2019 14:20; Scan Operator: 123; Page: x/y
  

Комментарии:

1. Извините, но я не знаю токены во время выполнения, поэтому я не могу их настроить

2. Но у вас есть доступ к ним во время выполнения? Другими словами, если вы обнаружите, что одним из ключевых слов является @Charge , как бы вы нашли значение для его замены?

3. Я не хотел сказать, что вы можете сделать это с помощью словаря, это был просто мой пример, внутри делегата вы можете написать любой код, который хотите получить, и вернуть значение для каждого ключевого слова.

4. коллекция (словарь) содержит это значение, а ключевое слово является просто ключом для этого словаря

5. То есть вы хотите сказать, что тогда мой код будет работать?

Ответ №3:

Это может сработать:

  var Charge = "phosphoric acid";
 var CurrentDate = "24.04.2019";
 var CurrentTime = "14:20";
 var ScanOperatorUserID = "123";
 var interpolated = $"{Charge}; {CurrentDate} {CurrentTime}; Scan Operator: {ScanOperatorUserID}; Page: x/y";
 string parsedWatermarkFormat = "phosphoric acid; 24.04.2019 14:20; Scan Operator: 123; Page: x/y";
 Console.WriteLine(interpolated);
 Console.WriteLine(parsedWatermarkFormat);
 Console.ReadKey();
  

Надеюсь, это поможет.

Ответ №4:

Я делаю это наоборот. Получите словарь и замените любое упоминание ключа.

 foreach(KeyValuePair<string,string> variable in variableDictionary )
                {
                    fileContent = fileContent.Replace("$("   variable.Key   ")", variable.Value);
                }