我寫了一個名爲StringTemplate
類,允許像String.Format
格式的對象,但其名稱,而不是佔位符索引。這裏有一個例子:正則表達式的String.Format樣工具
string s = StringTemplate.Format("Hello {Name}. Today is {Date:D}, and it is {Date:T}.",
new { Name = "World", Date = DateTime.Now });
爲了實現這個結果,我期待已久的佔位符,並與指標取代它們。然後我將結果格式字符串傳遞給String.Format
。
這工作得很好,當有一倍大括號,這是一個轉義序列除外。期望的行爲(其是相同的String.Format
)如下所述:
- 「你好{名稱}」應該格式化爲的 「Hello World」
- 「你好{{名稱}} 「格式應爲的 」Hello(名稱)「
- 」你好{{{名}}}「格式應爲」你好{}世界「
- 「你好{{{{名}}}}」格式應爲「你好{{名稱}}」
等等......
但我現在經常表達沒有檢測到轉義序列,並始終把括號作爲佔位符之間的字符串,所以我得到的東西像「你好{0}」。
這裏是我當前的正則表達式:
private static Regex _regex = new Regex(@"{(?<key>\w+)(?<format>:[^}]+)?}", RegexOptions.Compiled);
如何修改這個正則表達式忽略逃脫括號?什麼似乎真的很辛苦,是我應檢測根據括號的數量是否是奇數佔位符,甚至......我想不出一個簡單的方法,用正則表達式來做到這一點,是它甚至可能嗎?
爲了完整起見,這裏的StringTemplate
類的完整代碼:
public class StringTemplate
{
private string _template;
private static Regex _regex = new Regex(@"{(?<key>\w+)(?<format>:[^}]+)?}", RegexOptions.Compiled);
public StringTemplate(string template)
{
if (template == null)
throw new ArgumentNullException("template");
this._template = template;
}
public static implicit operator StringTemplate(string s)
{
return new StringTemplate(s);
}
public override string ToString()
{
return _template;
}
public string Format(IDictionary<string, object> values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
Dictionary<string, int> indexes = new Dictionary<string, int>();
object[] array = new object[values.Count];
int i = 0;
foreach (string key in values.Keys)
{
array[i] = values[key];
indexes.Add(key, i++);
}
MatchEvaluator evaluator = (m) =>
{
if (m.Success)
{
string key = m.Groups["key"].Value;
string format = m.Groups["format"].Value;
int index = -1;
if (indexes.TryGetValue(key, out index))
{
return string.Format("{{{0}{1}}}", index, format);
}
}
return string.Format("{{{0}}}", m.Value);
};
string templateWithIndexes = _regex.Replace(_template, evaluator);
return string.Format(templateWithIndexes, array);
}
private static IDictionary<string, object> MakeDictionary(object obj)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (var prop in obj.GetType().GetProperties())
{
dict.Add(prop.Name, prop.GetValue(obj, null));
}
return dict;
}
public string Format(object values)
{
return Format(MakeDictionary(values));
}
public static string Format(string template, IDictionary<string, object> values)
{
return new StringTemplate(template).Format(values);
}
public static string Format(string template, object values)
{
return new StringTemplate(template).Format(values);
}
}
我最近自己走了這條路,最後建立一個解析佔位符的簡單狀態機要比找出如何獲得正則表達式更容易。另外,當我最終不得不將我的分隔符更改爲方括號時(因爲'FlowDocument'有一些沒有很好記錄的行爲,而且我已經開始使用大括號),所以有很多問題我沒有遇到如果我使用正則表達式,我會有。 – 2010-03-03 20:47:03
是的,我應該使用狀態機來代替......但無論如何,我的代碼現在可以按照我的想法工作,所以我不會改變它,除非我必須;) – 2010-03-03 22:52:48
@ThomasLevesque,你會發布你使用的代碼是什麼? – smartcaveman 2013-02-26 03:40:16