正則表達(dá)式簡(jiǎn)介

翻譯:NorthTibet

原文出處:Regular Expressions


  有些新手對(duì)正則表達(dá)式不是很熟悉,有必要在此作一簡(jiǎn)單回顧。如果你是正則表達(dá)式高手,可以不用看這一部分。
  正則表達(dá)式是描述字符串集的字符串。例如,正則表達(dá)式“Mic*”描述所有包含“Mic”,后跟零個(gè)或多個(gè)字符的字符串。Mickey、Microsoft、Michelangelo 或 Mic 本身都是例子。句號(hào)“.”匹配任何字符,“+”類似“*”,但至少要一個(gè)字符,所以“Mic+”匹配前述所有除“Mic”以外的串。[a-z]指一個(gè)匹配范圍,所以[a-zA-Z_0-9]匹配字母、數(shù)字或下劃線。Regex 稱之為單詞字符,可以將它寫成“\w”。所以“\w+”匹配至少有一個(gè)字符的單詞字符序列——換句話說(shuō),叫 C 符號(hào)(C tokens)。那么這樣一來(lái),幾乎所有的C 符號(hào)都不能以數(shù)字開頭,因此,下面這個(gè)正則表達(dá)式是正確的:“^[a-zA-Z_]\w*$”。專用字符“^”意思是“以...開始”(除非它位于某個(gè)范圍之內(nèi),這時(shí)它的意思是“非”),“$”意思是“結(jié)尾”,那么“^[a-zA-Z_]\w*$”意思就是:以字母或下劃線開始的字母、數(shù)字或下劃線字符串。
  正則表達(dá)式在對(duì)輸入進(jìn)行有效性驗(yàn)證時(shí)非常有用。\d 匹配數(shù)字,{n}匹配重復(fù)n次,于是 ^5\d{15}$ 匹配5開頭的16位數(shù)字,也即是說(shuō) MasterCard 信用卡號(hào)碼。那 ^[45]\d{15}$ 就是Visa 卡號(hào),它以4開頭。你可以用大括弧對(duì)表達(dá)式進(jìn)行分組,下面是個(gè)測(cè)試。這個(gè)表達(dá)式描述的是什么呢?
^\d{5}(-\d{4}){0,1}$

提示:{0,1} 意思是重復(fù)0次或1次(可以縮寫成問(wèn)號(hào) ?)。想出來(lái)了嗎?該表達(dá)式意思是:五個(gè)數(shù)字后重復(fù)0次或1次(破折號(hào)后跟四個(gè)數(shù)字)。它匹配 02142和98007-4235,但不匹配 3245 或 2345-98761。這也就是美國(guó)的郵政編碼。大括弧將 ZIP+4 部分分組,所以{0,1}修飾符將應(yīng)用于整個(gè)分組。
  以上我僅淺嘗即止地說(shuō)明了正則表達(dá)式能做什么。我還沒(méi)提到替換,由于我沒(méi)有具體資料,所以不敢描述在 Unicode 中會(huì)怎么樣。但你能感覺(jué)到正則表達(dá)式有多么強(qiáng)大。多年來(lái)它們乃 UNIX 的中流砥柱,并且在Web 編程和 Perl 這樣的語(yǔ)言中更臻完善,其對(duì) HTML 的操作幾乎完全是對(duì)文本的處理。正則表達(dá)式在 Windows 中一直沒(méi)有得到充分使用,直到 .NET 框架面世,它才正式成為 Windows 家族的一員。

框架 Regex 類

.NET 框架用 Regex 類實(shí)現(xiàn)正則表達(dá)式,并有三個(gè)支持類:Match、Group 和 Capture (參見 Figure A)。典型情況下,你創(chuàng)建 Regex 并用輸入串調(diào)用 Regex::Match 來(lái)獲得第一個(gè) Match,或用 Regex::Matches 來(lái)獲取所有匹配:

Regex *r = new Regex("\b\w+\b");
MatchCollection* mc = 
  r->Matches("abc ,_foo ,<& mumble7");
for (int i=0; i<mc->Count; i++) {
   Match *m = mc->Index(i);
   Console.WriteLine(m->Value);
}
  這將顯示“abc”,“foo”和“mumble7”,每個(gè)匹配在一行。這個(gè)例子引入了一個(gè)專門的字符 \b,所謂錨或原子零寬度斷言,就像 ^(開始)和$(結(jié)尾)。\b 指定某個(gè)單詞的邊界,所以“\b\w+\b”意思是用單詞分隔的一個(gè)或多個(gè)單詞字符。
 


Figure A Regex 類

  正則表達(dá)式中的每個(gè)括弧表達(dá)式都構(gòu)成一個(gè) Group。Regex::Groups 返回作為集合的 Groups,它決不會(huì)是空,因?yàn)檎麄€(gè)正則表達(dá)式本身即是一組。Groups 很重要,因?yàn)樗鼈兪鼓氵M(jìn)行邏輯 OR 匹配,如“(ying|yong)”,它們使你將限定符應(yīng)用到子表達(dá)式,并讓你吸取匹配的單獨(dú)部分。正文的 Figure 1 中我的 RegexTest 程序運(yùn)行后用郵編為例顯示分組。
  在所有函數(shù)中最強(qiáng)大的函數(shù)要數(shù) Regex::Replace,它使得正則表達(dá)式的威力驚人地強(qiáng)大。和許多開發(fā)人員一樣,過(guò)去在多次傳遞字符串到多行編輯控件之前,我常常不得不手工將 “\n” 轉(zhuǎn)換為“\r\n”,但使用 Regex::Replace,這個(gè)操作簡(jiǎn)直易如反掌。

s = Regex::Replace(s,"\n","\r\n");

  Regex::Match 和 Replace 具備靜態(tài)重載,所以你可以不用創(chuàng)建對(duì)象,以快速使用正則表達(dá)式。我最喜歡的 Regex::Replace 重載之一是帶有一個(gè)委托參數(shù),使你能用過(guò)程代碼動(dòng)態(tài)計(jì)算替換文本——參見正文中那個(gè)有趣的例子。
  一些警告:每一種正則表達(dá)式的實(shí)現(xiàn)是有不太一樣的。例如,在 Perl 中,{,1}是{0,1}的速記版,而微軟的老大們不是那樣做的。要當(dāng)心一些微小的差別。權(quán)威的 .NET Regex 資料請(qǐng)參考 MSDN 庫(kù)中的 “Regular Expressions as a Language”。