本頁內容
引言Microsoft®.NET Framework 對正則表達式的支持是一流的,甚至在 Microsoft® ASP.NET 中也有依賴正則表達式語言的控件。本文介紹了深入學習正則表達式的基礎知識和推薦內容。 本文主要面向對正則表達式知之甚少或沒有使用經驗,但卻熟悉 ASP.NET、可借助 .NET 編程的初學者。此外,希望本文連同 regular expression cheat sheet 成為有正則表達式使用經驗的開發者的手頭參考資料或進修資料。本文討論內容如下:
通常,如果對本文或對正則表達式有疑問,請訪問 http://www.aspadvice.com/,通過 regex mailing list 提出問題。編寫此文時其中已有 350 多個訂戶參與。 正則表達式使用歷史簡介正則表達式設計于五十年代,存在至今。正則表達式最初用于描述“正則集”,它們是一些神經生理學家研究的模式。正則表達式最早由數學家 Stephen Kleene 提出,最終由 Ken Thompson 在兩種非常流行的文本實用程序 qed 和 grep 中使用。Jeffrey Friedl 在其著作“Mastering Regular Expressions (2nd edition)”中對此作了進一步闡述。建議那些希望更多了解正則表達式理論和歷史的人看看這本書。 在最近的五十年中,正則表達式逐漸從模糊深奧的數學概念發展為在各類工具和軟件包中應用的主要功能。盡管數十年來很多 UNIX 工具都支持正則表達式,但僅僅是近十年來,它才在大部分 Windows 開發者工具包中得到體現。在 Microsoft® Visual Basic® 6 或 Microsoft® VBScript 中,即使情況理想,正則表達式仍難以使用。但隨著.NET Framework 的推行,正則表達式的支持發展到極點,所有 Microsoft 開發者和所有 .NET 語言都可以使用正則表達式。 那么,正則表達式究竟是什么呢?正則表達式是一種語言,它可以明確描述文本字符串中的模式。除了簡單描述這些模式之外,正則表達式引擎通?捎糜诒闅v匹配,并使用模式作為分隔符來將字符串解析為子字符串,或以智能方式替換文本或重新設置文本格式。正則表達式為解決與文本處理有關的許多常見任務提供了有效而簡捷的方式。 在討論正則表達式時,通常以正則表達式匹配(或不匹配)的文本為基礎分析正則表達式。本文(以及 System.Text.RegularExpressions 類)將在正則表達式交互操作中引用 3 個參與對象:正則表達式的“模式”、“輸入”字符串和字符串內的所有模式的“匹配”。 簡單表達式最簡單的正則表達式大家都已熟悉,即文字字符串。特定的字符串可通過文字本身加以描述;像 foo 這樣的正則表達式模式可精確匹配輸入的字符串 foo。在本例中,也將匹配如下輸入:The food was quite tasty,如果希望精確匹配,這可能不是預期結果。 當然,使用正則表達式匹配等于它自身的精確字符串是沒有價值的實現,不能體現正則表達式的真正作用。假如不查找 foo,而是查找以字母 f 開頭的所有單詞,或所有 3 個字母的單詞,那該怎么辦?目前,這超出了文字字符串的合理范圍。我們需要更加深入地研究正則表達式。下面是一個文字表達式示例及一些匹配的輸入。
限定符限定符提供了一種簡單方法,用于指定在模式中允許特定字符或字符集自身重復出現的次數。有 3 個非顯式限定符:
限定符始終引用限定符前(左邊)的模式,通常是單個字符,除非使用括號創建模式組。下面是一些模式示例及匹配的輸入。
除了指定給定模式準確出現 0 或 1 次之外,? 字符還可強制模式或子模式匹配數目最少的字符(如果匹配輸入字符串中的多個字符)。 除了非顯式限定符(一般叫做限定符,但為區別于下一組,故稱非顯式限定符)之外,還有顯式限定符。在模式出現次數方面,限定符的概念非常模糊。使用顯式限定符則可準確指定數字、范圍或數字集。顯式限定符位于所應用的模式的后邊,這一點與正則限定符一樣。顯式限定符使用花括號 {} 及其中的數字值表示模式出現次數的上下限。例如,x{5} 將準確匹配 5 個 x 字符 (xxxxx)。如果僅指定一個數字,則表示次數上限;如果數字后跟一個逗號,如 x{5,},表示匹配任何出現次數大于 4 的 x 字符。下面是一些模式示例及匹配的輸入。
元字符在正則表達式中,有一種意義特殊的構造,即元字符。目前已知的元字符有很多,如 *、?、+ 和 {} 字符。其他字符在正則表達式語言中都有特殊的含義。這些字符包括:$ ^ . [ ( | ) ] 和 \。 .(句點或點)元字符是最簡單但最常用的一個字符。它可匹配任何單字符。如果要指定某些模式可包含任意組合的字符,使用句點非常有用,但一定要在特定長度范圍內。此外,我們知道表達式將對包含在較長字符串中的所有模式進行匹配,假如只需要精確匹配模式,又該怎么辦?這在驗證方案中經常出現,例如,要確保用戶輸入的郵政編碼或電話號碼的格式正確。使用 ^ 元字符可指定字符串(或行)的開始,使用 $ 元字符可指定字符串(或行)的結束。通過將這些字符添加到模式的開始和結束處,可強制模式僅匹配精確匹配的輸入字符串。如果 ^ 元字符用在方括號 [ ] 指定的字符類的開頭,也有特殊的含義。具體內容見下。 \ (反斜杠)元字符既可根據特殊含義“轉義”字符,也可指定預定義集合元字符的實例。同樣,具體內容見下。為了在正則表達式中包括文字樣式的元字符,必須使用反斜杠進行“轉義”。例如,如果要匹配以“c:\”開始的字符串,可使用:^c:\\。注意,要使用 ^ 元字符指出字符串必須以此模式作為開始,然后用反斜杠元字符轉義文字反斜杠。 |(管道)元字符用于交替指定,特別用于在模式中指定“此或彼”。例如,a|b 將匹配包含“a”或“b”的任何輸入內容,這與字符類 [ab] 非常類似。 最后,括號 ( ) 用于給模式分組。它允許使用限定符讓一個完整模式出現多次。為了便于閱讀,或分開匹配特定的輸入部分,可能允許分析或重新設置格式。 下面列出元字符的一些使用示例。
字符類字符類是正則表達式中的“迷你”語言,在方括號 [ ] 中定義。最簡單的字符類只不過是括號中的一個字符表,如 [aeiou]。在表達式中使用字符類時,可在模式的此位置使用其中任何一個字符(但只能使用一個字符,除非使用了限定符)。請注意,不能使用字符類定義單詞或模式,只能定義單個字符。 要指定任何數值數字,可以使用字符類 [0123456789]。但是,由于這樣使用字符不大方便,所以要通過在括號中使用連字符 - 來定義字符的范圍。連字符在字符類中有特殊的含義(不是在正則表達式中,因此,準確地說它不能叫正則表達式元字符),且僅在連字符不是第一個字符時,連字符才在字符類中有特殊含義。要使用連字符指定任何數值數字,可以使用 [0-9]。小寫字母也一樣,可以使用 [a-z],大寫字母可以使用 [A-Z]。連字符定義的范圍取決于使用的字符集。因此,字符在(例如)ASCII 或 Unicode 表中出現的順序確定了在范圍中包括的字符。如果需要在范圍中包括連字符,將它指定為第一個字符。例如:[-.?] 將匹配 4 個字符中任何一個字符(注意,最后的字符是個空格)。另請注意,正則表達式元字符在字符類中不做特殊處理,所以這些元字符不需要轉義?紤]到字符類是與其他正則表達式語言分開的一種語言,因此字符類有自己的規則和語法。 如果使用字符 ^ 作為字符類的第一個字符來否定此類,也可以匹配字符類成員以外的任何字符。因此,要匹配任何非元音字符,可以使用字符類 [^aAeEiIoOuU]。注意,如果要否定連字符,應將連字符作為字符類的第二個字符,如 [^-]。記住,^ 在字符類中的作用與它在正則表達式模式中的作用完全不同。 下面列出操作中使用的一些字符類。
在 .NET Framework 的下一版中,代碼名“Whidbey”作為一種新功能被添加到字符類中,稱作字符類差 (character class subtraction)。它的主要作用是,允許從一個字符類中減去另一個字符類,可提供更可讀的方式描述某些模式。該規范可通過以下地址訪問:http://www.gotdotnet.com/team/clr/bcl/TechArticles/techarticles/Specs/Regex/CharacterClassSubtraction.doc。它的語法類似 [a-z-[aeiou]],匹配所有的小寫輔音字母。 預定義的集合元字符使用目前提供的工具可以完成很多工作。但是,要使用 [0-9] 表示模式中的每個數值數字,或(更糟)使用 [0-9a-zA-Z]表示任何字母數字字符,還有一段相當漫長的過程。為了減輕處理這些常用但冗長模式的痛苦,事先定義了預定義元字符集合。正則表達式的不同實現定義了不同的預定義元字符集合,下面描述的預定義元字符集合在 .NET Framework 中得到 System.Text.RegularExpressions API 的支持。這些預定義元字符的標準語法是,在反斜杠 \ 后跟一個或多個字符。多數預定義元字符只有一個字符,它們的使用很容易,是冗長字符類的理想替代字符。以下是兩個示例:\d 匹配所有數值數字,\w 匹配所有單詞字符(字母數字加下劃線)。例外情況是一些特定字符代碼匹配,此時必須指定所匹配字符的地址,如 \u000D 將匹配 Unicode 回車符。下面列出一些最常用的字符類及其等效的元字符。
表達式示例很多人都喜歡通過示例學習,下面即提供一些表達式示例。要獲取更多示例,請訪問以下地址中的正則表達式聯機數據庫:http://www.regexlib.com/。
ASP.NET 中的驗證ASP.NET 提供了一套驗證控件,與使用舊的(或愿意的話使用傳統的) ASP 處理任務相比,驗證控件使在 Web 窗體上驗證輸入變得非常容易。其中一個非常有效的驗證器是 RegularExpressionValidator,如您所料,它允許您提供必須匹配輸入的正則表達式來驗證輸入。設置控件的 ValidationExpression 屬性可指定正則表達式的模式。下面顯示了驗證郵政代碼字段的驗證程序: <asp:RegularExpressionValidator runat="server" id="ZipCodeValidator" ControlToValidate="ZipCodeTextBox" ErrorMessage="Invalid ZIP code format; format should be either 12345 or 12345-6789." ValidationExpression="(\d{5}(-\d{4})?" /> 使用 RegularExpressionValidator 要注意幾個問題:
正則表達式 API除了 ASP.NET 驗證控件,在.NET 中使用正則表達式的大多數情況都要使用 System.Text.RegularExpressions 命名空間中發現的類。特別是那些您希望熟悉的主類 Regex、Match 和 MatchCollection。 順便說一下,正則表達式縮寫樣式 regex 的發音究竟是 /reg-eks/ 還是 /rej-eks/,還有一些爭議。本人傾向于后者,但兩種發音都有專家贊同,所以選擇哪個發音由您自己決定。 Regex 類有大量的方法和屬性,如果您以前沒有用過它,可能會感到無所適從。下面匯總了一些最常用的方法:
除了指定很多方法外,還有一些選項可以指定,通常在 Regex 對象構造函數中。由于這些選項是位屏蔽的一部分,或許可以同時指定這些選項(如,可以同時指定 Multiline 和 Singleline)。
使用正則表達式常執行的操作包括:驗證、匹配和替換。大多數情況下,可以使用 Regex 類的靜態方法完成這些操作,不需要實例化 Regex 類本身。要執行驗證,全部要做的就是必建或找到正確的表達式,然后使用 Regex 類的 IsMatch() 方法將表達式應用到輸入字符串中。例如,下面的函數演示了如何使用正則表達式驗證郵政編碼: private void ValidateZipButton_Click(object sender, System.EventArgs e) { String ZipRegex = @"^\d{5}$"; if(Regex.IsMatch(ZipTextBox.Text, ZipRegex)) { ResultLabel.Text = "ZIP is valid!"; } else { ResultLabel.Text = "ZIP is invalid!"; } } 類似的,可以使用靜態 Replace() 方法將匹配替換為特定字符串,如下所示: String newText = Regex.Replace(inputString, pattern, replacementText); 最后,可以使用如下代碼遍歷輸入字符串的匹配集合: private void MatchButton_Click(object sender, System.EventArgs e) { MatchCollection matches = Regex.Matches(SearchStringTextBox.Text, MatchExpressionTextBox.Text); MatchCountLabel.Text = matches.Count.ToString(); MatchesLabel.Text = ""; foreach(Match match in matches) { MatchesLabel.Text += "Found" + match.ToString() + " at position " + match.Index + ".<br>"; } } 通常,在您需要指定默認方式以外的方式時,需要實例化 Regex 類的實例。特別是在設置選項時。例如,要創建忽略大小寫和模式空白區域的 Regex 實例,然后檢索與該表達式匹配的集合,則應使用如下代碼: Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); MatchCollection mc = re.Matches(inputString); 本文的下載文件中包括這些示例的完整使用版本,與簡單 ASP.NET 頁中的一樣。 免費工具Regulator (http://royo.is-a-geek.com/iserializable/regulator/) - 一種在客戶端運行的正則表達式測試工具,通過 Web 服務與 RegexLib 緊密集成,提供對“匹配”、“拆分”和“替換”等的支持。包括性能分析和語法突出顯示功能。 RegexDesigner.NET (http://www.sellsbrothers.com/tools/) - 一種功能強大的可視工具,可幫助構造并測試正則表達式。它可生成 C# 和/或 VB.NET 代碼和已編譯匯編代碼,幫助您將表達式集成到應用程序中。 Regular Expression Workbench (v2.0) (http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=C712F2DF-B026-4D58-8961-4EE2729D7322) - Eric Gunnerson 開發的工具,用于創建、測試和研究正則表達式。具有“Examine-o-matic”功能,允許將鼠標懸停在正則表達式的上方,對其含義進行解碼。 高級主題正則表達式有兩個不得不說的功能,一個是“命名組”,另一個是“四向處理”(lookaround processing)。由于這些功能很少使用,此處只簡單闡述一下。 使用命名組,您可單獨命名匹配組,然后在表達式中使用程序語言引用這些組。如果結合 Replace 方法重新設置輸入字符串的格式(通過重新排列順序、替換輸入字符串中的元素),這個功能特別有效。例如,假設日期使用 MM/DD/YYYY 格式的字符串,而您希望日期格式是 DD-MM-YYYY。此時,可編寫一個表達式捕獲第一種格式,遍歷它的匹配集合,并分析每個字符串,然后使用字符串操作建立替換字符串。這需要大量的代碼和大量的處理。如果使用命名組,您可完成同樣的任務,具體見下: String MDYToDMY(String input) { return Regex.Replace(intput, @"\b(?<month>\d{1,2})/(?<day>\d{1,2}/(?<year>\d{4})\b", "${day}- ${month}-${year}"); } 您還可以按編號或按名稱引用組。在任何情況下,這種引用通稱作“反向引用”。另一個經常使用反向引用的場合在匹配表達式本身,如下這個表達式用于查找重復的字母:[a-z]\1。它將匹配“aa”、“bb”、“cc”,但它不同于 [a-z]{2} 或 [a-z][a-z],后兩者是等效的,后兩者允許匹配“ab”或“ac”或任何其他兩個字母的組合。反向引用允許表達式記住表達式已經分析并匹配過的輸入字符串中的部分字符。 “四向處理”指很多正則表達式引擎所支持的正負 Lookahead 和 Lookbehind 功能。并不是所有的正則表達式引擎都支持驗證四向處理。這些構造不使用字符,即使它們可以匹配字符。有些模式可能在不使用四向處理的情況下無法描述。特別是當模式中存在的一部分依賴于另一部分,如果不使用四向處理,則不能描述這樣的模式。下面介紹了每個四向處理的語法。
密碼驗證是必需四向處理的一個示例。假定在密碼限制中,密碼必須介于 4 到 8 個字符,且必須至少包含一個數字。為此,您可以僅在匹配中測試 \d,然后使用字符串操作來測試長度。但要在正則表達式中實現這一切,必須使用 Lookahead。特別是正 lookahead,如下所示:^(?=.*\d).{4,8}$ |
文章來源于領測軟件測試網 http://www.kjueaiud.com/