我正在尝试创建一个通用的格式化程序/解析器组合.
示例场景:
var format = "{0}-{1}"
var arr = new[] { "asdf", "qwer" }
var res = string.Format(format, arr)
我想要做的是将格式化的字符串恢复回对象(字符串)数组.像(伪代码)的东西:
var arr2 = string.Unformat(format, res)
// when: res = "asdf-qwer"
// arr2 should be equal to arr
Run Code Online (Sandbox Code Playgroud)
有没有经验做过这样的事情?我正在考虑使用正则表达式(修改原始格式字符串,然后将其传递给Regex.Matches以获取数组)并为格式字符串中的每个占位符运行它.这是可行的还是还有其他更有效的解决方案?
Pro*_*ner 16
虽然有关丢失信息的注释有效,但有时您只想获取具有已知格式的字符串的字符串值.
一种方法是我的朋友写的这篇博文.他实现了一个名为的扩展方法string[] ParseExact()
,类似于DateTime.ParseExact()
.数据以字符串数组的形式返回,但如果您能够使用它,那么它非常方便.
public static class StringExtensions
{
public static string[] ParseExact(
this string data,
string format)
{
return ParseExact(data, format, false);
}
public static string[] ParseExact(
this string data,
string format,
bool ignoreCase)
{
string[] values;
if (TryParseExact(data, format, out values, ignoreCase))
return values;
else
throw new ArgumentException("Format not compatible with value.");
}
public static bool TryExtract(
this string data,
string format,
out string[] values)
{
return TryParseExact(data, format, out values, false);
}
public static bool TryParseExact(
this string data,
string format,
out string[] values,
bool ignoreCase)
{
int tokenCount = 0;
format = Regex.Escape(format).Replace("\\{", "{");
for (tokenCount = 0; ; tokenCount++)
{
string token = string.Format("{{{0}}}", tokenCount);
if (!format.Contains(token)) break;
format = format.Replace(token,
string.Format("(?'group{0}'.*)", tokenCount));
}
RegexOptions options =
ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
Match match = new Regex(format, options).Match(data);
if (tokenCount != (match.Groups.Count - 1))
{
values = new string[] { };
return false;
}
else
{
values = new string[tokenCount];
for (int index = 0; index < tokenCount; index++)
values[index] =
match.Groups[string.Format("group{0}", index)].Value;
return true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Cle*_*man 10
您无法取消格式化,因为信息丢失了.String.Format
是一种"破坏性"算法,这意味着你不能(总是)回去.
创建一个继承自的新类string
,在该类中添加一个跟踪"{0}-{1}"
和{ "asdf", "qwer" }
覆盖的成员ToString()
,并稍微修改一下代码.
如果它变得太棘手,只需创建相同的类,但不要继承string
并修改更多的代码.
IMO,这是最好的方法.