Подтвердить что ты не робот

Строка parse с использованием шаблона формата?

Если я могу форматировать строку, используя

string.Format("my {0} template {1} here", 1, 2)

Можно ли отменить процесс - я предоставляю шаблон и заполненную строку,.net возвращает arg0, arg1 и т.д.?

4b9b3361

Ответ 1

Нет элегантного способа отменить форматированную строку. Но вы можете попробовать это, если хотите простую функцию.

private List<string> reverseStringFormat(string template, string str)
{
     //Handels regex special characters.
    template = Regex.Replace(template, @"[\\\^\$\.\|\?\*\+\(\)]", m => "\\" 
     + m.Value);

    string pattern = "^" + Regex.Replace(template, @"\{[0-9]+\}", "(.*?)") + "$";

    Regex r = new Regex(pattern);
    Match m = r.Match(str);

    List<string> ret = new List<string>();

    for (int i = 1; i < m.Groups.Count; i++)
    {
        ret.Add(m.Groups[i].Value);
    }

    return ret;
}

Ответ 2

String.Format не может быть обратимым в общем случае.

Если у вас есть ровно один {0}, вполне возможно написать общий код, который хотя бы извлекает строковое представление значения. Вы определенно не можете отменить его для создания оригинальных объектов.

Примеры:

  • Несколько аргументов: string.Format("my{0}{1}", "aa", "aaa"); создает "myaaaaa", tring to reverse string.ReverseFormat("my{0}{1}", "myaaaaa") должен решить, как разделить "aaaaa" часть в 2 без какой-либо информации.

  • Невозможность обращения к типу данных string.Format("{0:yyyy}", DateTime.Now); приводит к 2011 году, большая часть информации о самой ценности потеряна.

Ответ 3

Один из способов сделать это - это регулярные выражения. Для вашего примера вы можете сделать:

Regex regex = new Regex("^my (.*?) template (.*?) here$");
Match match = regex.Match("my 53 template 22 here");
string arg0 = match.Groups[1].Value;    // = "53"
string arg1 = match.Groups[2].Value;    // = "22"

Нетрудно написать метод расширения, чтобы сделать именно то, что вы хотите на основе этой техники.

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

public static object[] ExtractFormatParameters(this string sourceString, string formatString)
{
    Regex placeHolderRegex = new Regex(@"\{(\d+)\}");
    Regex formatRegex = new Regex(placeHolderRegex.Replace(formatString, m => "(<" + m.Groups[1].Value + ">.*?)");
    Match match = formatRegex.Match(sourceString);
    if (match.Success)
    {
        var output = new object[match.Groups.Count-1];
        for (int i = 0; i < output.Length; i++)
            output[i] = match.Groups[i+1].Value;
        return output;
    }
    return new object[];
} 

Это позволит вам выполнить

object[] args = sourceString.ExtractFormatParameters("my {0} template {1} here");

Метод ОЧЕНЬ наивный и имеет много проблем, но он будет в основном искать любые заполнители в выражении формата и находить соответствующий текст в исходной строке. Он предоставит вам значения, соответствующие заполнителям, перечисленным слева направо, без ссылки на порядковый номер или любой формат, указанный в заполнителе. Эта функциональность может быть добавлена.

Другая проблема заключается в том, что любые специальные символы регулярных выражений в строке формата приведут к тому, что метод упадет. Для выполнения каких-либо специальных символов, которые являются частью formatString, необходимо выполнить некоторую дополнительную обработку formatRegex.

Ответ 4

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

Regex.Match("my (.*) template (.*) here", theFilledInString);

У меня нет VS open, поэтому я не могу проверить, правильно ли я имею имя метода, но вы поймете, что я имею в виду. Используя paranthesis, результат возврата будет иметь группы [0] и группы [1], содержащие ваши извлеченные соответствия.