我正在開發一個小型應用程序,需要用它們的值替換字符串中的.NET樣式「變量」。一個例子如下:使用正則表達式.NET樣式的可變擴展
替換:
「{d}/{MM}/{YYYY}」
隨着: 「31/12/2009」
我決定使用正則表達式來查找「{var}」的出現,但我不太確定如何正確地使用它。
我正在開發一個小型應用程序,需要用它們的值替換字符串中的.NET樣式「變量」。一個例子如下:使用正則表達式.NET樣式的可變擴展
替換:
「{d}/{MM}/{YYYY}」
隨着: 「31/12/2009」
我決定使用正則表達式來查找「{var}」的出現,但我不太確定如何正確地使用它。
如果你要使用正則表達式,和你有一個已知的模式,它沒有得到比使用匹配評估方法,而不是調用更簡單的更換了一堆時間:
void Main() // run this in LinqPad
{
string text = "I was here on {D}/{MMM}/{YYYY}.";
string result = Regex.Replace(text, "{[a-zA-Z]+}", ReplaceMatched);
Console.WriteLine(result);
}
private string ReplaceMatched(Match match)
{
if(match.Success)
{
switch(match.Value)
{
case "{D}":
return DateTime.Now.Day.ToString();
case "{YYYY}":
return DateTime.Now.Year.ToString();
default:
break;
}
}
// note, early return for matched items.
Console.WriteLine("Warning: Unrecognized token: '" + match.Value + "'");
return match.Value;
}
給結果
Warning: Unrecognized token: '{MMM}' I was here on 2/{MMM}/2009.
它沒有完全實施明顯。
下面是一些代碼,我在一個日誌實用程序,它幾乎正是你想要的使用,雖然格式稍有不同:
Regex rgx = new Regex("{([Dd]:([^{]+))}");
private string GenerateTrueFilename()
{
// Figure out the new file name
string lfn = LogFileName;
while (rgx.IsMatch(lfn))
{
Match m = rgx.Matches(lfn)[0];
string tm = m.Groups[1].Value;
if (tm.StartsWith("D:"))
{
string sm = m.Groups[2].Value;
string dts = DateTime.Now.ToString(sm);
lfn = lfn.Replace(m.Groups[0].Value, dts);
}
}
return lfn;
}
的RGX定義格式,目前實際上只有一種格式:
d:{datestring}
LOGFILENAME是在代碼別處定義的變量,但是有一個默認:
LogFileName = "LogFile.{D:yyyy-MM-dd}.log"
所以希望您能從中看到如何根據需要繼續處理其他變量。
正則表達式真的很強大,但也需要很多開銷。它可能會更簡單使用類似inputString.Replace("{var}", value)
代替:
void Foo()
{
string s = "{D}/{MM}/{YYYY}";
s = ReplaceTokenInString(s, "{D}", "31");
s = ReplaceTokenInString(s, "{MM}", "12");
s = ReplaceTokenInString(s, "{YYYY}", "2009");
}
string ReplaceTokenInString(string input, string token, string replacement)
{
input.Replace(token, replacement);
}
除了創建這2箇中間字符串....沒有什麼大不了的,只有3個替換字符串,但它不是很聰明。使用StringBuilder及其'方法sb.Replace可能會更好,當你認爲'程序'的重點是要取代東西。另外,爲什麼將事情與1行方法ReplaceTokenInString進行混淆,它確實實現了s.Replace的功能? – 2009-09-02 01:53:44
@Robert Paulson:使用StringBuilder進行替換不一定比創建新字符串更有效 - 如果令牌及其替換長度不同,則不會更有效。您的MatchEvaluator解決方案通過一次性完成所有事情,輕鬆擊敗兩種方法。 – 2009-09-02 02:53:33
@Alan M,真的,這就是爲什麼我說'可能',因爲我從來沒有描述它,但至少希望它更好。 – 2009-09-02 04:33:21
如果你正在做的具體日期,你應該考慮使用format string。很顯然,如果你做的不僅僅是這些,這對你無能爲力。
我用正則表達式做了它,並使用一個StringBuilder。我在源字符串中找到匹配項,並追加字符串和評估匹配項的塊。
StringBuilder text = new StringBuilder(snippet.Length * 2);
Regex pattern = new Regex("\\{[A-Za-z]+\\}");
MatchCollection matches = pattern.Matches(snippet);
if (matches.Count == 0) return snippet;
int from = 0;
foreach (Match match in matches)
{
text.Append(snippet.Substring(from, match.Index - from));
string variable = snippet.Substring(match.Index + 1, match.Length - 2);
text.Append(EvaluateVariable(variable));
from = match.Index + match.Length;
}
text.Append(snippet.Substring(from));
return text.ToString();
太棒了!您剛剛重新創建了Regex.Replace方法。你真的應該再看看羅伯特·保爾森的回答。 – 2009-09-02 05:51:51
是的,我甚至沒有注意到答案。我來自本地C++,去圖哈哈 – 2009-09-02 23:01:35
+1 - 我真正喜歡.NET regexps的兩件事是這樣的,並且能夠解析任意嵌套的構造。 – 2009-09-02 03:07:36