預(yù)定義的集合元字符
使用目前提供的工具可以完成很多工作。但是,要使用 [0-9] 表示模式中的每個(gè)數(shù)值數(shù)字,或(更糟)使用 [0 -9a -zA-Z]表示任何字母數(shù)字字符,還有一段相當(dāng)漫長(zhǎng)的過程。為了減輕處理這些常用但冗長(zhǎng)模式的痛苦,事先定義了預(yù)定義元字符集合。正則表達(dá)式的不同實(shí)現(xiàn)定義了不同的預(yù)定義元字符集合,下面描述的預(yù)定義元字符集合在 .NET Framework 中得到 System.Text.RegularExpressions API 的支持。這些預(yù)定義元字符的標(biāo)準(zhǔn)語(yǔ)法是,在反斜杠 \ 后跟一個(gè)或多個(gè)字符。多數(shù)預(yù)定義元字符只有一個(gè)字符,它們的使用很容易,是冗長(zhǎng)字符類的理想替代字符。以下是兩個(gè)示例:\d 匹配所有數(shù)值數(shù)字,\w 匹配所有單詞字符(字母數(shù)字加下劃線)。例外情況是一些特定字符代碼匹配,此時(shí)必須指定所匹配字符的地址,如 \u000D 將匹配 Unicode 回車符。下面列出一些最常用的字符類及其等效的元字符。
元字符 |
等效字符類 |
---|---|
\a |
匹配鈴聲(警報(bào));\u0007 |
\b |
匹配字符類外的字邊界,它匹配退格字符,\u0008 |
\t |
匹配制表符,\u0009 |
\r |
匹配回車符,\u000D |
\w |
匹配垂直制表符,\u000B |
\f |
匹配換頁(yè)符,\u000C |
\n |
匹配新行,\u000A |
\e |
匹配轉(zhuǎn)義符,\u001B |
\040 |
匹配 3 位 8 進(jìn)制 ASCII 字符。\040 表示空格(十進(jìn)制數(shù) 32)。 |
\x20 |
使用 2 位 16 進(jìn)制數(shù)匹配 ASCII 字符。此例中,\x2- 表示空格。 |
\cC |
匹配 ASCII 控制字符,此例中是 ctrl-C。 |
\u0020 |
使用 4 位 16 進(jìn)制數(shù)匹配 Unicode 字符。此例中 \u0020 是空格。 |
\* |
不代表預(yù)定義字符類的任意字符都只作為該字符本身對(duì)待。因此,\* 等同于 \x 2A(是文字 *,不是 * 元字符)。 |
\p{name} |
匹配已命名字符類“name”中的任意字符。支持名稱是 Unicode 組和塊范圍。例如,Ll、Nd、Z、IsGreek、IsBoxDrawing 和 Sc(貨幣)。 |
\p{name} |
匹配已命名字符類“name”中不包括的文本。 |
\w |
匹配任意單詞字符。對(duì)于非 Unicode 和 ECMAScript 實(shí)現(xiàn),這等同于 [a-zA-Z_0-9]。在 Unicode 類別中,這等同于 [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}]。 |
\W |
\w 的否定,等效于 ECMAScript 兼容集合 [^a-zA-Z_0-9] 或 Unicode 字符類別 [^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}]。 |
\s |
匹配任意空白區(qū)域字符。等效于 Unicode 字符類 [\f\n\r\t\v\x85\p{Z}]。如果使用 ECMAScript 選項(xiàng)指定 ECMAScript 兼容方式,\s 等效于 [ \f\n\r\t\v] (請(qǐng)注意前導(dǎo)空格)。 |
\S |
匹配任意非空白區(qū)域字符。等效于 Unicode 字符類別 [^\f\n\r\t\v\x85\p{Z}]。如果使用 ECMAScript 選項(xiàng)指定 ECMAScript 兼容方式,\S 等效于 [^ \f\n\r\t\v] (請(qǐng)注意 ^ 后的空格)。 |
\d |
匹配任意十進(jìn)制數(shù)字。在 ECMAScript 方式下,等效于 Unicode 的 [\p{Nd}]、非 Unicode 的 [0-9]。 |
\D |
匹配任意非十進(jìn)制數(shù)字。在 ECMAScript 方式下,等效于 Unicode 的 [\p{Nd}]、非 Unicode 的 [^0-9]。 |
表達(dá)式示例
很多人都喜歡通過示例學(xué)習(xí),下面即提供一些表達(dá)式示例。要獲取更多示例,請(qǐng)?jiān)L問以下地址中的正則表達(dá)式聯(lián)機(jī)數(shù)據(jù)庫(kù):http://www.regexlib.com/。
模式 |
說明 |
---|---|
^\d{5}$ |
5 個(gè)數(shù)值數(shù)字,如美國(guó)郵政編碼。 |
^(\d{5})|(\d{5}-\d{4}$ |
5 個(gè)數(shù)值數(shù)字或 5 個(gè)數(shù)字-短劃線-4 個(gè)數(shù)字。匹配 5 位數(shù)字格式的美國(guó)郵政編碼,或 5 位數(shù)字 + 4 位數(shù)字格式的美國(guó)郵政編碼。 |
^(\d{5}(-\d{4})?$ |
與前一個(gè)相同,但更有效。使用 ? 可使模式中的 4 位數(shù)字成為可選部分,而不是要求分別比較不同的兩個(gè)模式(通過另一種方式)。 |
^[+-]?\d+(\.\d+)?$ |
匹配任意有可選符號(hào)的實(shí)數(shù)。 |
^[+-]?\d*\.?\d*$ |
與上一個(gè)相同,但也匹配空字符串。 |
^(20|21|22|23|[01]\d)[0-5]\d$ |
匹配 24 小時(shí)制時(shí)間值。 |
/\*.*\*/ |
匹配 C 語(yǔ)言風(fēng)格的注釋 /* ... */ |
ASP.NET 中的驗(yàn)證
ASP.NET 提供了一套驗(yàn)證控件,與使用舊的(或愿意的話使用傳統(tǒng)的) ASP 處理任務(wù)相比,驗(yàn)證控件使在 Web 窗體上驗(yàn)證輸入變得非常容易。其中一個(gè)非常有效的驗(yàn)證器是 RegularExpressionValidator,如您所料,它允許您提供必須匹配輸入的正則表達(dá)式來驗(yàn)證輸入。設(shè)置控件的 ValidationExpression 屬性可指定正則表達(dá)式的模式。下面顯示了驗(yàn)證郵政代碼字段的驗(yàn)證程序:
<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 要注意幾個(gè)問題:
-
決不要使用驗(yàn)證程序要驗(yàn)證的控件中的空字符串來激活驗(yàn)證器。只有 RequiredFieldValidator 才可以捕獲空字符串。
-
您無需指定匹配字符的開始與結(jié)尾(^ 和$)- 它們是事先假設(shè)的。如果添加了開始與結(jié)尾,也沒有任何影響,不需要這樣做。
-
對(duì)于所有驗(yàn)證控件來說,必須在客戶端以及服務(wù)器端進(jìn)行驗(yàn)證。如果正則表達(dá)式不是 ECMAScript 兼容方式,客戶端驗(yàn)證將失敗。為了避免這種情況,確保表達(dá)式是 ECMAScript 兼容方式,否則只在服務(wù)器端進(jìn)行控件驗(yàn)證。
正則表達(dá)式 API
除了 ASP.NET 驗(yàn)證控件,在.NET 中使用正則表達(dá)式的大多數(shù)情況都要使用 System.Text.RegularExpressions 命名空間中發(fā)現(xiàn)的類。特別是那些您希望熟悉的主類 Regex、Match 和 MatchCollection。
順便說一下,正則表達(dá)式縮寫樣式 regex 的發(fā)音究竟是 /reg-eks/ 還是 /rej-eks/,還有一些爭(zhēng)議。本人傾向于后者,但兩種發(fā)音都有專家贊同,所以選擇哪個(gè)發(fā)音由您自己決定。
Regex 類有大量的方法和屬性,如果您以前沒有用過它,可能會(huì)感到無所適從。下面匯總了一些最常用的方法:
方法 |
說明 |
---|---|
Escape / Unescape |
字符串中的轉(zhuǎn)義元字符,用作表達(dá)式中的文字。 |
IsMatch |
如果正則表達(dá)式在輸入字符串中發(fā)現(xiàn)匹配,返回“Ture”。 |
Match |
如果在輸入字符串中發(fā)現(xiàn)匹配,則返回匹配對(duì)象。 |
Matches |
如果在輸入字符串中發(fā)現(xiàn)包含任何或全部匹配,則返回匹配集合對(duì)象。 |
Replace |
用給定的替換字符串替換輸入字符串中的匹配。 |
Split |
將輸入字符串拆分成用正則表達(dá)式匹配分開的數(shù)組元素時(shí),返回?cái)?shù)組字符串。 |
除了指定很多方法外,還有一些選項(xiàng)可以指定,通常在 Regex 對(duì)象構(gòu)造函數(shù)中。由于這些選項(xiàng)是位屏蔽的一部分,或許可以同時(shí)指定這些選項(xiàng)(如,可以同時(shí)指定 Multiline 和 Singleline)。
方法 |
說明 |
---|---|
Compiled |
當(dāng)在循環(huán)中執(zhí)行許多匹配操作時(shí)使用此選項(xiàng)。這可以節(jié)省每一循環(huán)的分析表達(dá)式步驟。 |
Multiline |
它與輸入字符串中的行數(shù)沒有關(guān)系。確切地說,它只修改 ^ 和 $ 的方式,以便匹配行開始 (BOL) 和行結(jié)尾 (EOL),而不是匹配整個(gè)輸入字符串的開始和結(jié)尾。 |
IgnoreCase |
使模式在匹配搜索字符串時(shí)忽略大小寫。 |
IgnorePatternWhitespace |
允許根據(jù)需要在模式中包括任意數(shù)量的空白區(qū)域,也支持使用 (?# 注釋 #) 語(yǔ)法在模式中加入注釋。 |
SingleLine |
它與輸入字符串中的行數(shù)沒有關(guān)系。更確切地說,它將導(dǎo)致 .(句點(diǎn))元字符匹配任意字符,而不是除 \n 之外的任意字符(默認(rèn)情況)。 |
使用正則表達(dá)式常執(zhí)行的操作包括:驗(yàn)證、匹配和替換。大多數(shù)情況下,可以使用 Regex 類的靜態(tài)方法完成這些操作,不需要實(shí)例化 Regex 類本身。要執(zhí)行驗(yàn)證,全部要做的就是必建或找到正確的表達(dá)式,然后使用 Regex 類的 IsMatch() 方法將表達(dá)式應(yīng)用到輸入字符串中。例如,下面的函數(shù)演示了如何使用正則表達(dá)式驗(yàn)證郵政編碼:
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!"; } }
類似的,可以使用靜態(tài) 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>"; } }
通常,在您需要指定默認(rèn)方式以外的方式時(shí),需要實(shí)例化 Regex 類的實(shí)例。特別是在設(shè)置選項(xiàng)時(shí)。例如,要?jiǎng)?chuàng)建忽略大小寫和模式空白區(qū)域的 Regex 實(shí)例,然后檢索與該表達(dá)式匹配的集合,則應(yīng)使用如下代碼:
Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); MatchCollection mc = re.Matches(inputString);
本文的下載文件中包括這些示例的完整使用版本,與簡(jiǎn)單 ASP.NET 頁(yè)中的一樣。
免費(fèi)工具
Regulator (http://royo.is-a-geek.com/iserializable/regulator/) - 一種在客戶端運(yùn)行的正則表達(dá)式測(cè)試工具,通過 Web 服務(wù)與 RegexLib 緊密集成,提供對(duì)“匹配”、“拆分”和“替換”等的支持。包括性能分析和語(yǔ)法突出顯示功能。
RegexDesigner.NET (http://www.sellsbrothers.com/tools/) - 一種功能強(qiáng)大的可視工具,可幫助構(gòu)造并測(cè)試正則表達(dá)式。它可生成 C# 和/或 VB.NET 代碼和已編譯匯編代碼,幫助您將表達(dá)式集成到應(yīng)用程序中。
Regular Expression Workbench (v2.0) (http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=C712F2DF-B026-4D58-8961-4EE2729D7322) - Eric Gunnerson 開發(fā)的工具,用于創(chuàng)建、測(cè)試和研究正則表達(dá)式。具有“Examine-o-matic”功能,允許將鼠標(biāo)懸停在正則表達(dá)式的上方,對(duì)其含義進(jìn)行解碼。
高級(jí)主題
正則表達(dá)式有兩個(gè)不得不說的功能,一個(gè)是“命名組”,另一個(gè)是“四向處理”(lookaround processing)。由于這些功能很少使用,此處只簡(jiǎn)單闡述一下。
使用命名組,您可單獨(dú)命名匹配組,然后在表達(dá)式中使用程序語(yǔ)言引用這些組。如果結(jié)合 Replace 方法重新設(shè)置輸入字符串的格式(通過重新排列順序、替換輸入字符串中的元素),這個(gè)功能特別有效。例如,假設(shè)日期使用 MM/DD/YYYY 格式的字符串,而您希望日期格式是 DD-MM-YYYY。此時(shí),可編寫一個(gè)表達(dá)式捕獲第一種格式,遍歷它的匹配集合,并分析每個(gè)字符串,然后使用字符串操作建立替換字符串。這需要大量的代碼和大量的處理。如果使用命名組,您可完成同樣的任務(wù),具體見下:
String MDYToDMY(String input) { return Regex.Replace(intput, @"\b(?<month>\d{1,2})/(?<day>\d{1,2}/(?<year>\d{4})\b", "${day}- ${month}-${year}"); }
您還可以按編號(hào)或按名稱引用組。在任何情況下,這種引用通稱作“反向引用”。另一個(gè)經(jīng)常使用反向引用的場(chǎng)合在匹配表達(dá)式本身,如下這個(gè)表達(dá)式用于查找重復(fù)的字母:[a-z]\1。它將匹配“aa”、“bb”、“cc”,但它不同于 [a-z]{2} 或 [a-z][a-z],后兩者是等效的,后兩者允許匹配“ab”或“ac”或任何其他兩個(gè)字母的組合。反向引用允許表達(dá)式記住表達(dá)式已經(jīng)分析并匹配過的輸入字符串中的部分字符。
“四向處理”指很多正則表達(dá)式引擎所支持的正負(fù) Lookahead 和 Lookbehind 功能。并不是所有的正則表達(dá)式引擎都支持驗(yàn)證四向處理。這些構(gòu)造不使用字符,即使它們可以匹配字符。有些模式可能在不使用四向處理的情況下無法描述。特別是當(dāng)模式中存在的一部分依賴于另一部分,如果不使用四向處理,則不能描述這樣的模式。下面介紹了每個(gè)四向處理的語(yǔ)法。
語(yǔ)法 |
說明 |
---|---|
(?=...) |
正 Lookahead |
(?!...) |
負(fù) Lookahead |
(?<=...) |
正 Lookbehind |
(?<!...) |
負(fù) Lookbehind |
密碼驗(yàn)證是必需四向處理的一個(gè)示例。假定在密碼限制中,密碼必須介于 4 到 8 個(gè)字符,且必須至少包含一個(gè)數(shù)字。為此,您可以僅在匹配中測(cè)試 \d,然后使用字符串操作來測(cè)試長(zhǎng)度。但要在正則表達(dá)式中實(shí)現(xiàn)這一切,必須使用 Lookahead。特別是正 lookahead,如下所示:^(?=.*\d).{4,8}$
結(jié)論
正則表達(dá)式是一種描述文本模式的極有效方法,它使文本模式成為字符串驗(yàn)證和操作的極好資源。.NET Framework 通過 System.Text.RegularExpressions 命名空間(特別是其中的 Regex 類)提供了對(duì)正則表達(dá)式的強(qiáng)大支持。使用 API 很簡(jiǎn)單,但編寫正確的正則表達(dá)式通常比較費(fèi)力。但幸運(yùn)的是,正則表達(dá)式可以重復(fù)使用,您可以通過網(wǎng)絡(luò)中的各種聯(lián)機(jī)資源,從中找出其他人設(shè)計(jì)的表達(dá)式,或者在創(chuàng)建表達(dá)式遇到困難時(shí)得到幫助。
資源
正則表達(dá)式庫(kù) http://www.regexlib.com/
正則表達(dá)式討論列表 http://aspadvice.com/login.aspx?ReturnUrl=%2fSignUp%2flist.aspx%3fl%3d68%26c%3d16&l=68&c=16
正則表達(dá)式論壇 http://forums.regexadvice.com/
正則表達(dá)式 Web 日志 http://blogs.regexadvice.com/
Mastering Regular Expressions (O'Reilly),作者 Jeffrey Friedl http://www.regex.info/
.NET 正則表達(dá)式參考 http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemTextRegularExpressions.asp
Jscript 正則表達(dá)式語(yǔ)法 http://www.msdn.microsoft.com/library/en-us/script56/html/js56jsgrpRegExpSyntax.asp
正則表達(dá)式信息 http://www.regular-expressions.info/
Steven A. Smith 是 Microsoft 在 ASP.NET 技術(shù)方面的最有價(jià)值專家 (MVP),是 ASPAlliance.com 和 DevAdvice.com 的總裁和所有者。此外,他也是 ASPSmith Ltd(一家重點(diǎn)提供 .NET 培訓(xùn)的公司)的所有者和首席教師。他撰寫了兩本著作:“ASP.NET Developer's Cookbook”和“ASP.NET By Example”,并在 MSDN 和 AspNetPRO 雜志上發(fā)表了一些文章。Steve 每年都在各種會(huì)議上發(fā)表演講,是 INETA 聯(lián)絡(luò)處的成員。Steve 擁有企業(yè)管理碩士學(xué)位及計(jì)算機(jī)科學(xué)工程理學(xué)士學(xué)位。