Parse string using format template?
If I can format a string using
string.Format("my {0} template {1} here", 1, 2)
can I reverse the process - I pr开发者_运维技巧ovide the template and a filled-in string, .net returns arg0, arg1, etc.?
There's no elegant way to reverse the formatted string. But you can try this if you want a simple function.
private List<string> reverseStringFormat(string template, string str)
{
//Handles 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 is not reversable in general case.
If you have exactly one {0} it is actaully possible to write generic code that at least extract string representation of the value. You definitely can't reverse it to produce original objects.
Samples:
Multiple arguments:
string.Format("my{0}{1}", "aa", "aaa");
produces "myaaaaa", tring to reversestring.ReverseFormat("my{0}{1}", "myaaaaa")
have to decide how to split "aaaaa" portion in 2 without any information.Inability to reverse to data type
string.Format("{0:yyyy}", DateTime.Now);
results in 2011, most of information about value itself lost.
One way to do this would be regular expressions. For your example you could do:
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"
It wouldn't be hard to write an extension method to do exactly what you want based on this technique.
Just for fun, here's my first naive attempt. I haven't tested this but it should be close.
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[];
}
This will allow you to do
object[] args = sourceString.ExtractFormatParameters("my {0} template {1} here");
The method is VERY naive and has many problems, but it will basically find any placeholders in the format expression, and find the corresponding text in the source string. It will give you the values corresponding to the placeholders listed from left to right, without reference to ordinal, or any format specified in the placeholder. This functionality could be added.
Another problem is that any special regex characters in the format string will cause the method to fall over. Some more processing of formatRegex
would need to be done to escape any special characters that are part of formatString
.
Use regular expressions to parse out group matches.
Regex.Match("my (.*) template (.*) here", theFilledInString);
I don't have VS open, so I can't verify if I have the method name right, but you'll know what I mean. By using paranthesis, the returned match result will have groups[0] and groups[1] containing your extracted matches.
精彩评论