作為文本處理的利器——Perl語言對正則表達式的最強大支持起到了重要的作用,正因為如此,許多其他語言在加入正則表達式引擎的時候都會或多或少的兼顧perl風格的正則表達式,開發(fā)出相應的引擎。本人使用perl語言處理文本有一些時間,同時也有幾年php開發(fā)的經(jīng)歷,像php就有兼容perl的正則表達式引擎,其對應的正則表達式函數(shù)就是以p為前綴,如preg_replace、preg_match、preg_split。.NET 類庫當然也提供了正則表達式的支持,位于System.Text.RegularExpressions命名空間下的Regex類封裝了所有正則表達式的屬性和使用方法。本文以C#語言詳細敘述一下.NET類庫下的這個Regex類,可以發(fā)現(xiàn)所有的語言對正則表達式的支持都是萬變不離其宗,以類比推理的方式學習非常好。
使用過正則表達式的朋友都知道,正則表達式就是指定一個規(guī)則去處理一些復雜的文本(如果是簡單的處理可以使用一般語言內(nèi)置的字符串處理函數(shù)就可以了,而且效率會更好)。這樣需要達到的效果無非就是用一個模式去替換字符串中的特定項為另一特定項、用一個模式去匹配文本中感興趣的部分內(nèi)容、用一個特殊的模式去拆分文本。
- 構(gòu)造函數(shù):用于構(gòu)造一個正則表達式對象,源碼的聲明如下:
其中聲明為public的構(gòu)造函數(shù)是可以直接使用的,前者使用一個正則表達式字符串構(gòu)造,后者使用正則表達式字符串和表達式選項構(gòu)造對象。其中正則表達式選項RegexOptions是一個枚舉類型,用于設置正則表達式的模式修正,C#的這個選項有如下項目:
Multiline —— 將字符串視為多行,“.”就不能匹配換行符(掩碼為2)
Singleline—— 將字符串視為單行,“.”就可以匹配換行符(掩碼為16)
IgnorePatternWhitespace —— 忽略模式表達式中的非轉(zhuǎn)義空白,并啟用#表示的注釋(掩碼為32)
None —— 不設置選項(掩碼為0)
IgnoreCase —— 忽略字符串中的大小寫(掩碼為1)
RightToLeft —— 將默認的從左至右的搜索改為從右至左(掩碼為64)
Compiled —— 將正則表達式編譯為程序集,可以加快運行速度,但是會增加啟動時間(掩碼為8)
CultureInvariant —— 忽略語言中的區(qū)域性差異(掩碼為512)
ExplicitCapture —— 指定有效的捕獲僅為形式為 (?<name>...) 的顯式命名或編號的組,使得未命名的圓括號可以充當非捕獲組(掩碼為4)
ECMAScript —— 為表達式啟用符合 ECMAScript 的行為,只能與IgnoreCase、Multiline和Compiled選項一起使用(掩碼為256)
上述選項都是使用掩碼方式存儲的,因此多個選項選擇的時候直接使用按位與“|”操作符連接起來即可。
- 匹配(Match):使用模式進行匹配的時候,.NET提供了IsMatch和Match以及Matches三個函數(shù),第一個返回布爾值用來表示是否匹配成功,第二個則是返回匹配得到的結(jié)果Match對象,包含了匹配的結(jié)果內(nèi)容,第三個則是返回一個Match對象的集合,包含了所有匹配的對象。上述函數(shù)的所有聲明如下:
IsMatch提供了一個對輸入字符串進行匹配和指定起始位置匹配,同時也提供了對應的靜態(tài)函數(shù),用于省去構(gòu)造對象的麻煩,直接傳入模式進行匹配。使用如下代碼得到的結(jié)果如下圖。
string text = @"12345qwert";
if (Regex.IsMatch(text, @"[\d]+"))
{
Console.WriteLine("success");
}
else
{
Console.WriteLine("fail");
}

Match函數(shù)也是同樣的提供了輸入字符串匹配,和指定起始位置開始匹配,或者同事指定匹配長度。對應的靜態(tài)版本類似。匹配成功返回的是一個Match對象,包含了如下信息:包含的匹配信息Capture、匹配得到的對應的分組信息Group,Capture包含了匹配得到的字符串Value、長度Length和在源字符串中的起始位置Index,Group則擁有組名稱、是否成功Success,同時Match對象包含了NextMatch屬性用于只想下一個匹配得到的Match對象(如果有多個匹配成功項的話),還有Result方法用一個字符串去替換當前匹配到的字符串。Match函數(shù)僅返回匹配到的第一個分組,也就是分組0,整個正則表達式匹配到的整體。
Matches函數(shù)則是同樣提供了輸入字符串和指定起始位置開始,返回匹配得到的所有Match對象集合。
string text = @"12345qwert67890";
Regex rg = new Regex( @"(?<first>[\d])\d+");
if (rg.IsMatch(text,0))
{
MatchCollection mts = rg.Matches(text,0);
foreach(Match mt in mts )
{
Console.WriteLine("success:" + mt.Value);
}
}
else
{
Console.WriteLine("fail");
}

- 替換(Replace):其實在Match函數(shù)中也提供了Result方法用來替換匹配項,但是功能不夠充分,以下是Regex類中的替換方法:
替換方法Replace方法可以直接對輸入文本替換成給定的文本,也有指定替換次數(shù)和起始位置。同時可以使用MatchEvaluator對象進行替換,此對象使用Replace單詞匹配到的Match對象為參數(shù)的一個委托,對每個匹配項進行替換。對于簡單的替換可以直接使用字符串參數(shù)替換匹配項以及指定替換次數(shù)或者起始位置,但是對于復雜的匹配則要使用MatchEvaluator委托進行,可以參考http://www./regex-replace。
- 分割(Split):分割為找到匹配項后以此階段源字符串,返回字符數(shù)組。定義如下:
這個方法的定義比較簡單,就是找到匹配項然后從此字符串拆分獲取拆分的結(jié)果,同時可以指定拆分的數(shù)組元素個數(shù)。測試如下:
string text = @"12345qwert67890";
Regex rg = new Regex( @"(?<first>[\d])\d+");
string [] strArr = rg.Split(text,10);
foreach(string str in strArr )
{
Console.WriteLine("success:{0}", str);
}

從上述圖中結(jié)果可以看出,對于有分組的時候,是按照源字符串中的位置順序進行匹配都進行拆分。
除上述內(nèi)容外,.NET的Regex類還提供了如下方法:
Unescape / Escape—— 轉(zhuǎn)換輸入字符串中的任何轉(zhuǎn)義字符 / 轉(zhuǎn)換普通字符為轉(zhuǎn)義字符
CompileToAssembly —— 將一個或多個指定的Regex 對象編譯為命名程序集
GroupNameFromNumber / GroupNumberFromName —— 對命名過的分組得到組號或者相反操作
GetGroupNames / GetGroupNumbers —— 返回匹配到的多組匹配項的組號或組名