天天看點

C#中的正規表達式

對于正規表達式的應用, 基本上可以分為驗證、提取、分割和替換。僅僅利用Regex類就可以實作驗證和簡單替換。

利用Regex類實作驗證

經曆2009年的備案和DNS停止解析風波之後,大部分的帶有回報性的網站 和論壇都對一些敏感詞進行了過濾,包含有這類敏感詞的文章要麼内容被替換要麼被禁止發表,利用Regex類就可以實作這個功能,下面是一個例子:

///

/// 檢查字元串中是否有“孫權”這個敏感詞

///

public void IsMatchDemo()

{

string source = "劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操許攸郭嘉需晃袁紹"; 

     Regex regex = new Regex("孫權"); 

     //if (Regex.IsMatch(source, "孫權")) 

     //下面這句和上面被注釋掉的一句作用的同樣的 

     if (regex.IsMatch(source)) 

     { 

             Console.WriteLine("字元串 中包含有敏感詞:孫權!"); 

     } 
           

輸出結果:字元串中包含 有敏感詞:孫權!

對于上面的例子,如果要 檢查的字元串中包含“孫權”這個關鍵詞就會在控制台上輸出提示,當然在實際的應用中可能是包含有被禁止的詞語的内容不允許送出而不是僅僅提示了。不過這類 情況仍有辦法可以繞過,可以使用“孫-權”或“孫+權”來替換孫權進而來繞過驗證。

對于中文字元串還比較好 說,對于英文的字元串還要考慮每個字母的大小寫情況了。比如我們禁止在内容中出現某個關鍵詞(如太CCTV的CCTV,或者CCAV),難道我們要針對字元串中每個字母的大小寫情況進行多種情況的組合驗證?不,完全沒有必要,下面就是一個例子:

///

/// 檢查字元串中是否有“def”的任何大小寫形式

///

public void IsMatchDemoWithOption()

{

string source = "劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操DEF許攸郭嘉需晃袁紹"; 

     Regex regex = new Regex("def",RegexOptions.IgnoreCase); 

     if (regex.IsMatch(source)) 

     { 

             Console.WriteLine("字元串 中包含有敏感詞:def!"); 

     } 
           

}

輸出結果:字元串中包含 有敏感詞:def!

在上面的例子中,執行個體化Regex時采用了兩個帶參數的構造函數,其中第二個參 數就是上一篇中提到的RegexOptions枚舉,RegexOptions.IgnoreCase表示比對字元串的時候不管大小寫是否一緻。

此外,在Regex中存在着一些功能相同的靜态方法和執行個體方法, 如:IsMatch()方法,在第一個例子中我 還寫出了兩種方法的執行個體,如下:

Regex regex = new Regex(“孫權”);

//if (Regex.IsMatch(source, “孫權”))

//下面這句和上面被注釋掉的一句作用的同樣的

if (regex.IsMatch(source))

其實在.NET Framework中很多類都有這樣類似的情況,在System.IO命名空間下還有File及FileInfo這樣的靜态類和非靜态類的情況,其實它們提供 了相似的功能,用小沈陽的話說“這是為什麼呢”?有部分是出自效率的考慮,并且也有出自讓代碼編寫友善和看起來簡潔的因素。對于偶爾一半次為之的情況,建 議使用靜态方法,這樣有可能會提高效率(因為采用靜态方法調用的正規表達式會被内部緩存,預設情況下會緩存15個,可以通過設定Regex類的CacheSize屬性來更改緩存個數),如果是要在循環中多次 使用,那就采用執行個體方法吧。

使用Regex類進行替換

上面的處理僅僅是檢視提 交的内容中是否有被禁止的關鍵詞,其實有時候還可以做到将被禁止的關鍵詞進行替換,例如将上面用到的字元串中的任何形式的"ABC"替換成"|",下面就是一個例子:

///

/// 實作字元串替換功能

///

public void Replace()

{

string source = "劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操DEF許攸郭嘉需晃袁紹"; 

     Regex regex = new Regex("abc", RegexOptions.IgnoreCase); 

     string result=regex.Replace(source, "|"); 

     Console.WriteLine("原始字元串:" + source); 

     Console.WriteLine("替換後的字元串:" + result); 
           

}

輸出結果:

原始字元串:劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操DEF許攸郭嘉需晃袁紹

替換後的字元串:劉備|關羽|張飛|趙雲|諸葛亮|孫權|周瑜|魯肅|曹操DEF許攸郭嘉需晃袁紹

實際上有時候我們遇到的 情況可能不僅僅這麼簡單,例如有時候我們希望将字元串中的任何形式的“ABC”及“DEF”實作HTML形式的加粗,也就是替換成

abc

def

這種形式,當然還保持和原來一緻的大小寫形式,代碼如下:

///

/// 實作字元串替換功能

///

public void ReplaceMatchEvaluator()

{

string source = "劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操DEF許攸郭嘉需晃袁紹"; 

     Regex regex = new Regex("[A-Z]{3}", RegexOptions.IgnoreCase); 

     string result = regex.Replace(source, new MatchEvaluator(OutPutMatch)); 

     Console.WriteLine("原始字元串:" + source); 

     Console.WriteLine("替換後的字元串:" + result); 
           

}

///

/// MatchEvaluator委托中調用的方法,可以對比對結果進行處理

///

/// 操作過程中的單個正規表達式比對

///

private string OutPutMatch(Match match)

{

return "<b>" + match.Value + "</b>"; 
           

}

輸出結果如下:

原始字元串:劉備ABC關羽ABc張飛Abc趙雲abc諸葛亮aBC孫權abC周瑜AbC魯肅aBc曹操DEF許攸郭嘉需晃袁紹

替換後的字元串:劉備

ABC

關羽

ABc

張飛

Abc

趙雲

abc

諸葛亮

aBC

孫權

abC

周瑜

AbC

魯肅

aBc

曹操

DEF

許攸郭嘉需晃袁紹

在上面的例子中,我們使 用了MatchEvaluator委托,并且還涉及到了Match類(Match類将會在下一篇講述),在MatchEvaluator委托中使用到的Match類表示了單個的正規表達式比對,通過改變match執行個體中Value的值來達到完成替換的目的。

在本篇中僅僅是講述了Regex類的一些簡單用法,也沒有講述正規表達式的相 關知識,不過即使如此也能減輕我們的一部分工作,學習和靈活運用正規表達式是一個長期積累的過程。