作為文本處理的利器——Perl語(yǔ)言對(duì)正則表達(dá)式的最強(qiáng)大支持起到了重要的作用,正因?yàn)槿绱耍?/font>許多其他語(yǔ)言在加入正則表達(dá)式引擎的時(shí)候都會(huì)或多或少的兼顧perl風(fēng)格的正則表達(dá)式,開(kāi)發(fā)出相應(yīng)的引擎。本人使用perl語(yǔ)言處理文本有一些時(shí)間,同時(shí)也有幾年php開(kāi)發(fā)的經(jīng)歷,像php就有兼容perl的正則表達(dá)式引擎,其對(duì)應(yīng)的正則表達(dá)式函數(shù)就是以p為前綴,如preg_replace、preg_match、preg_split。.NET 類庫(kù)當(dāng)然也提供了正則表達(dá)式的支持,位于System.Text.RegularExpressions命名空間下的Regex類封裝了所有正則表達(dá)式的屬性和使用方法。本文以C#語(yǔ)言詳細(xì)敘述一下.NET類庫(kù)下的這個(gè)Regex類,可以發(fā)現(xiàn)所有的語(yǔ)言對(duì)正則表達(dá)式的支持都是萬(wàn)變不離其宗,以類比推理的方式學(xué)習(xí)非常好。
使用過(guò)正則表達(dá)式的朋友都知道,正則表達(dá)式就是指定一個(gè)規(guī)則去處理一些復(fù)雜的文本(如果是簡(jiǎn)單的處理可以使用一般語(yǔ)言內(nèi)置的字符串處理函數(shù)就可以了,而且效率會(huì)更好)。這樣需要達(dá)到的效果無(wú)非就是用一個(gè)模式去替換字符串中的特定項(xiàng)為另一特定項(xiàng)、用一個(gè)模式去匹配文本中感興趣的部分內(nèi)容、用一個(gè)特殊的模式去拆分文本。
- 構(gòu)造函數(shù):用于構(gòu)造一個(gè)正則表達(dá)式對(duì)象,源碼的聲明如下:
其中聲明為public的構(gòu)造函數(shù)是可以直接使用的,前者使用一個(gè)正則表達(dá)式字符串構(gòu)造,后者使用正則表達(dá)式字符串和表達(dá)式選項(xiàng)構(gòu)造對(duì)象。其中正則表達(dá)式選項(xiàng)RegexOptions是一個(gè)枚舉類型,用于設(shè)置正則表達(dá)式的模式修正,C#的這個(gè)選項(xiàng)有如下項(xiàng)目:
Multiline —— 將字符串視為多行,“.”就不能匹配換行符(掩碼為2)
Singleline—— 將字符串視為單行,“.”就可以匹配換行符(掩碼為16)
IgnorePatternWhitespace —— 忽略模式表達(dá)式中的非轉(zhuǎn)義空白,并啟用#表示的注釋(掩碼為32)
None —— 不設(shè)置選項(xiàng)(掩碼為0)
IgnoreCase —— 忽略字符串中的大小寫(xiě)(掩碼為1)
RightToLeft —— 將默認(rèn)的從左至右的搜索改為從右至左(掩碼為64)
Compiled —— 將正則表達(dá)式編譯為程序集,可以加快運(yùn)行速度,但是會(huì)增加啟動(dòng)時(shí)間(掩碼為8)
CultureInvariant —— 忽略語(yǔ)言中的區(qū)域性差異(掩碼為512)
ExplicitCapture —— 指定有效的捕獲僅為形式為 (?<name>...) 的顯式命名或編號(hào)的組,使得未命名的圓括號(hào)可以充當(dāng)非捕獲組(掩碼為4)
ECMAScript —— 為表達(dá)式啟用符合 ECMAScript 的行為,只能與IgnoreCase、Multiline和Compiled選項(xiàng)一起使用(掩碼為256)
上述選項(xiàng)都是使用掩碼方式存儲(chǔ)的,因此多個(gè)選項(xiàng)選擇的時(shí)候直接使用按位與“|”操作符連接起來(lái)即可。
- 匹配(Match):使用模式進(jìn)行匹配的時(shí)候,.NET提供了IsMatch和Match以及Matches三個(gè)函數(shù),第一個(gè)返回布爾值用來(lái)表示是否匹配成功,第二個(gè)則是返回匹配得到的結(jié)果Match對(duì)象,包含了匹配的結(jié)果內(nèi)容,第三個(gè)則是返回一個(gè)Match對(duì)象的集合,包含了所有匹配的對(duì)象。上述函數(shù)的所有聲明如下:
IsMatch提供了一個(gè)對(duì)輸入字符串進(jìn)行匹配和指定起始位置匹配,同時(shí)也提供了對(duì)應(yīng)的靜態(tài)函數(shù),用于省去構(gòu)造對(duì)象的麻煩,直接傳入模式進(jìn)行匹配。使用如下代碼得到的結(jié)果如下圖。
string text = @"12345qwert";
if (Regex.IsMatch(text, @"[\d]+"))
{
Console.WriteLine("success");
}
else
{
Console.WriteLine("fail");
}
Match函數(shù)也是同樣的提供了輸入字符串匹配,和指定起始位置開(kāi)始匹配,或者同事指定匹配長(zhǎng)度。對(duì)應(yīng)的靜態(tài)版本類似。匹配成功返回的是一個(gè)Match對(duì)象,包含了如下信息:包含的匹配信息Capture、匹配得到的對(duì)應(yīng)的分組信息Group,Capture包含了匹配得到的字符串Value、長(zhǎng)度Length和在源字符串中的起始位置Index,Group則擁有組名稱、是否成功Success,同時(shí)Match對(duì)象包含了NextMatch屬性用于只想下一個(gè)匹配得到的Match對(duì)象(如果有多個(gè)匹配成功項(xiàng)的話),還有Result方法用一個(gè)字符串去替換當(dāng)前匹配到的字符串。Match函數(shù)僅返回匹配到的第一個(gè)分組,也就是分組0,整個(gè)正則表達(dá)式匹配到的整體。
Matches函數(shù)則是同樣提供了輸入字符串和指定起始位置開(kāi)始,返回匹配得到的所有Match對(duì)象集合。
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):其實(shí)在Match函數(shù)中也提供了Result方法用來(lái)替換匹配項(xiàng),但是功能不夠充分,以下是Regex類中的替換方法:
替換方法Replace方法可以直接對(duì)輸入文本替換成給定的文本,也有指定替換次數(shù)和起始位置。同時(shí)可以使用MatchEvaluator對(duì)象進(jìn)行替換,此對(duì)象使用Replace單詞匹配到的Match對(duì)象為參數(shù)的一個(gè)委托,對(duì)每個(gè)匹配項(xiàng)進(jìn)行替換。對(duì)于簡(jiǎn)單的替換可以直接使用字符串參數(shù)替換匹配項(xiàng)以及指定替換次數(shù)或者起始位置,但是對(duì)于復(fù)雜的匹配則要使用MatchEvaluator委托進(jìn)行,可以參考http://www./regex-replace。
- 分割(Split):分割為找到匹配項(xiàng)后以此階段源字符串,返回字符數(shù)組。定義如下:
這個(gè)方法的定義比較簡(jiǎn)單,就是找到匹配項(xiàng)然后從此字符串拆分獲取拆分的結(jié)果,同時(shí)可以指定拆分的數(shù)組元素個(gè)數(shù)。測(cè)試如下:
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é)果可以看出,對(duì)于有分組的時(shí)候,是按照源字符串中的位置順序進(jìn)行匹配都進(jìn)行拆分。
除上述內(nèi)容外,.NET的Regex類還提供了如下方法:
Unescape / Escape—— 轉(zhuǎn)換輸入字符串中的任何轉(zhuǎn)義字符 / 轉(zhuǎn)換普通字符為轉(zhuǎn)義字符
CompileToAssembly —— 將一個(gè)或多個(gè)指定的Regex 對(duì)象編譯為命名程序集
GroupNameFromNumber / GroupNumberFromName —— 對(duì)命名過(guò)的分組得到組號(hào)或者相反操作
GetGroupNames / GetGroupNumbers —— 返回匹配到的多組匹配項(xiàng)的組號(hào)或組名