Если я могу форматировать строку, используя
string.Format("my {0} template {1} here", 1, 2)
Можно ли отменить процесс - я предоставляю шаблон и заполненную строку,.net возвращает arg0, arg1 и т.д.?
Если я могу форматировать строку, используя
string.Format("my {0} template {1} here", 1, 2)
Можно ли отменить процесс - я предоставляю шаблон и заполненную строку,.net возвращает arg0, arg1 и т.д.?
Нет элегантного способа отменить форматированную строку. Но вы можете попробовать это, если хотите простую функцию.
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;
}
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 году, большая часть информации о самой ценности потеряна.
Один из способов сделать это - это регулярные выражения. Для вашего примера вы можете сделать:
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
.
Используйте регулярные выражения для разбора групповых совпадений.
Regex.Match("my (.*) template (.*) here", theFilledInString);
У меня нет VS open, поэтому я не могу проверить, правильно ли я имею имя метода, но вы поймете, что я имею в виду. Используя paranthesis, результат возврата будет иметь группы [0] и группы [1], содержащие ваши извлеченные соответствия.