1        概述

初學正則時,對於Regex類不熟悉,遇到問題不知道該用哪種方法解決,本文結合一些正則應用的典型應用場景,介紹一下Regex類的基本應用。這裡重點進行.NET類的介紹,對於正則的運用,不做深入探討。

正則的應用最終都是進行模式的匹配,而根據目的的不同,基本上可以分為以下幾種應用:驗證、提取、替換、分割。結合.NET提供的控制元件、類以及類的方法,可以很方便的實現這些應用。

以下將結合一些典型的應用場景,對.NET中常見的類、方法及屬性進行介紹。本文旨在.NET類基礎用法的引導,對於其中涉及到的正則表示式不做深入探討。本文適合於在.NET平臺下使用正則的初學者。

2        基礎應用

2.1     驗證

驗證的目的是為了判斷輸入的源字串是否符合某一規律或規則,根據需求的不同,可能是校驗整個源字串,也可能只是校驗其中一個子串。

驗證在.NET中一般有兩種應用,一種是在驗證控制元件RegularExpressionValidator中,另一種是在程式中。

2.1.1  驗證控制元件RegularExpressionValidator

RegularExpressionValidator是.NET自帶的一種客戶端驗證控制元件,通過簡單的設定,即可完成對某控制元件輸入值的校驗。

基本應用語法如下:

<asp:RegularExpressionValidator

ID="RegularExpressionValidator1"

runat="server"

ControlToValidate="TextBox1"

ErrorMessage="RegularExpressionValidator"

ValidationExpression="^([1-9][0-9]*|0)(/.[0-9][2])?$">

</asp:RegularExpressionValidator>

對於RegularExpressionValidator控制元件不做過多介紹,只是說明一下使用時需要注意的幾點:

1、  RegularExpressionValidator進行的是客戶端驗證;

2、  RegularExpressionValidator中正則使用的是JavaScript語法規則;

3、  RegularExpressionValidator控制元件不能驗證輸入是否為空。

由於RegularExpressionValidator做的是客戶端驗證,很容易被跳過,所以在使用RegularExpressionValidator驗證的同時,還要做伺服器端驗證。

RegularExpressionValidator最終是要生成客戶端的JavaScript程式碼進行驗證的,所以RegularExpressionValidator使用的正則要求符合JavaScript語法規則,與.NET的幾點區別:

1、  不支援逆序環視,也就是(?<=Expression)和(?<!Expression)這樣的語法;

2、  元字元僅支援ASCII碼,即/w等價於[a-zA-Z0-9_],/d等價於[0-9]

RegularExpressionValidator控制元件一般是用來驗證某一控制元件輸入的字串整體是否符合某一規則的,所以通常情況下“^”和“$”是必不可少的;在使用“|”表示“或”的關係時,一定要用“()”來限定“|”作用範圍,比如0-100可以寫作“^([1-9]?[0-9]|100)$”。

RegularExpressionValidator是不能驗證輸入是否為空的,驗證是否為空要用RequiredFieldValidator控制元件。

RegularExpressionValidator驗證控制元件是.NET為方便客戶端驗證封裝的一組驗證控制元件之一,但由於RegularExpressionValidator受限於支援的正則語法規則,只能做有限的格式校驗,一些複雜的校驗可以通過自己寫JavaScript程式碼來實現,也是很簡單的。

2.1.2  程式驗證——IsMatch()

程式中的校驗基本上就是使用IsMatch方法,驗證的物件可能是源字串的整體,也可能只是其中一個子串。

驗證源字串的整體是否符合某一規則,與使用RegularExpressionValidator時的需求基本上一致,不過由於是在.NET程式中,所以使用的是.NET的語法,比JavaScript中要強大得多。比如驗證一個文字框輸入的字串是否符合某一規則,就是一個典型的驗證整體的需求。

舉例1:驗證textBox1輸入內容,要求整數部分為0或正整數,小數可有可無,有小數時必須為2位。

Regex reg = new Regex(@"^(?:[1-9][0-9]*|0)(?:/.[0-9]{2})?$");

if (reg.IsMatch(textBox1.Text))

{

richTextBox2.Text = "輸入格式正確!";

}

else

{

richTextBox2.Text = "輸入格式錯誤!";

}

由於是對源字串的整體進行驗證,所以“^”和“$”是必不可少的。否則驗證的結果可能是錯誤的,比如正則表示式“(?:[1-9][0-9]*|0)(?:/.[0-9]{2})?”,在輸入“0.123”時是可以匹配成功的,匹配結果為“0.12”,此時正則只起到了匹配的作用,沒有起到驗證的作用。

驗證源字串的區域性是否符合某一規則,就是對於源字串中子串的校驗,通常是用來判斷源字串中是否包含,或是不包含符合某一規律的子串,作用類似於string類中的IndexOf。

舉例2(參考問兩個正則表示式):

資料:

1985aaa1985bb

bcae1958fiefadf1955fef

atijc1944cvkd

df2564isdjfef2564d

abc1234def5678ghi5678jkl

需求1:驗證字串中任意位置出現的連續四個數字在整個字串中是否有重複,有重複為True,無重複為False。

以上資料需求1的驗證結果為True的應為:

1985aaa1985bb

df2564isdjfef2564d

abc1234def5678ghi5678jkl

因為需求中指明是任意位置的連續4個數字是否有重複,所以在找到重複前,要遍歷源字串中每一個位置時行驗證,這樣就不能限定開始識別符號“^”;而在匹配過程中,除非一直到結尾仍找不到重複,否則只要匹配到有重複的位置就可以了,這樣也不需要結束識別符號“$”,所以這是典型的對字串的子序列驗證的需求。

程式碼實現:

string[] test = new string[] { "1985aaa1985bb", "bcae1958fiefadf1955fef", "atijc1944cvkd","df2564isdjfef2564d", "abc1234def5678ghi5678jkl" };

Regex reg = new Regex(@"(/d{4})(?:(?!/1).)*/1");

foreach (string s in test)

{

richTextBox2.Text += "源字串:  " + s.PadRight(25, ' ') + "驗證結果:  " + reg.IsMatch(s) + "/n";

}

/*--------輸出--------

源字串:  1985aaa1985bb            驗證結果:  True

源字串:  bcae1958fiefadf1955fef   驗證結果:  False

源字串:  atijc1944cvkd            驗證結果:  False

源字串:  df2564isdjfef2564d       驗證結果:  True

源字串:  abc1234def5678ghi5678jkl 驗證結果:  True

*/

由於涉及到了重複問題,所以這裡用到了反向引用,對於反向引用的細節,可以參考正則基礎之——反向引用

需求2:驗證字串中第一個出現的連續4個數字是否有重複,有重複為True,無重複為False。

以上資料需求2的驗證結果為True的應為:

1985aaa1985bb

df2564isdjfef2564d

因為需求中指明是第一個是否有重複,所以需要有開始識別符號“^”,來保證是第一個出現的連續4個數字;而在匹配過程中,除非一直到結尾仍找不到重複,否則只要匹配到有重複的位置就可以了,這樣也不需要結束識別符號“$”,所以這仍是對字串的子序列驗證的需求,只不過相對於需求1來說,加了一個限定條件。

程式碼實現:

string[] test = new string[] { "1985aaa1985bb", "bcae1958fiefadf1955fef", "atijc1944cvkd","df2564isdjfef2564d", "abc1234def5678ghi5678jkl" };

Regex reg = new Regex(@"^(?:(?!/d{4}).)*(/d{4})(?:(?!/1).)*/1");

foreach (string s in test)

{

richTextBox2.Text += "源字串:  " + s.PadRight(25, ' ') + "驗證結果:  " + reg.IsMatch(s) + "/n";

}

/*--------輸出--------

源字串:  1985aaa1985bb            驗證結果:  True

源字串:  bcae1958fiefadf1955fef   驗證結果:  False

源字串:  atijc1944cvkd            驗證結果:  False

源字串:  df2564isdjfef2564d       驗證結果:  True

源字串:  abc1234def5678ghi5678jkl 驗證結果:  False

*/

2.2     提取——Match()、Matches()

提取主要是從源字串中,取得一個或多個符合某一規律或規則的子串。一般來說,在字串處理中,提取應用比較廣泛。提取時用得比較多的是Match()和Matches()方法,以及結果處理時Match類和MatchCollection類的一些方法,有時也會用到Capture類的一些方法。

2.2.1  提取單次匹配內容——Match()

當需要提取的內容只有一個,或是隻需要獲取第一次成功匹配的內容時,可以使用Match()方法。當使用Match()方法時,只要在某一位置匹配成功,就不再繼續嘗試匹配,並返回一個Match型別的物件。

舉例:提取姓名

源字串:姓名:張三,性別:男,年齡:25

程式碼實現:

string test = "姓名:張三,性別:男,年齡:25";

Regex reg = new Regex(@"(?<=姓名:)[^,]+");

Match m = reg.Match(test);

if (m.Success)    //驗證是否匹配成功

{

richTextBox2.Text = m.Value;

}

/*--------輸出--------

張三

*/

雖然Match()只是取一次匹配,但是可以通過捕獲組來獲取多個指定子串,比如獲取第一個<a…>標籤的連結和文字。

string test = "abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";

Regex reg = new Regex(@"(?is)<a(?:(?!href=).)href=(['""]?)(?<url>[^""/s>]*)/1[^>]*>(?<text>(?:(?!</?a/b).)*)</a>");

Match m = reg.Match(test);

if(m.Success)

{

richTextBox2.Text += m.Groups["url"].Value + "/n";      //連結

richTextBox2.Text += m.Groups["text"].Value + "/n";     //文字

}

/*--------輸出--------

www.test1.com

測試一

*/

對於捕獲組捕獲結果的引用,還有一種方式

string test = "abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";

Regex reg = new Regex(@"(?is)<a(?:(?!href=).)href=(['""]?)(?<url>[^""/s>]*)/1[^>]*>(?<text>(?:(?!</?a/b).)*)</a>"); Match m = reg.Match(test);

if(m.Success)

{

richTextBox2.Text += m.Result("${url}") + "/n";      //連結

richTextBox2.Text += m.Result("${text}") + "/n";     //文字

}

/*--------輸出--------

www.test1.com

測試一

*/

這兩種方法獲取的結果都是一樣的,使用哪一種,通常根據個人習慣而定。

2.2.2  提取多次匹配內容——Matches()

當需要提取的內容有多個,並且需要提取所有符合規律的子串時,可以使用Matches()方法。當使用Matches()方法時,需要遍歷源字串的每一個位置進行嘗試匹配,匹配結束返回一個MatchCollection型別的物件。

對於1.2.1節提到的提取連結和文字的例子,如果提取的是全部連結和文字,而不僅僅是第一個時,可以使用Matches()方法。

string test = "abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";

Regex reg = new Regex(@"(?is)<a(?:(?!href=).)href=(['""]?)(?<url>[^""/s>]*)/1[^>]*>(?<text>(?:(?!</?a/b).)*)</a>");

MatchCollection mc = reg.Matches(test);

foreach(Match m in mc)

{

richTextBox2.Text += m.Groups["url"].Value + "/n";      //連結

richTextBox2.Text += m.Groups["text"].Value + "/n";     //文字

}

/*--------輸出--------

www.test1.com

測試一

www.test2.com

測試二

*/

對於Matches(),某些場景下,也可以通過Count屬性,用做統計符合某一規律的子串出現的次數,例如統計字串中獨立的“3”出現的次數。

string test = "137,1,33,4,3,6,21,3,35,93,2,98";

Regex reg = new Regex(@"/b3/b");

int count = reg.Matches(test).Count;    //2

這時候關心的只是匹配成功的次數,對於匹配的內容是不關心的,所以實現這種需求時,正則應儘量簡潔,能達到目的即可,這樣可以加快匹配效率,減少資源佔用。比如上面的提取連結的源字串中,統計<a…>標籤出現的次數,一般來說,如下程式碼即可達到目的了。

string test = "abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";

Regex reg = new Regex(@"(?i)<a/b");

int count = reg.Matches(test).Count;    //2

2.2.3  捕獲組匹配過程集合——Capture

在某些情況下,一個正則表示式整體匹配一次時,其中的捕獲組可能會匹配多次。

舉例

源字串:<region name=oldslist col=1 row=2 order=asc>abcsadf </region> jfdsajf  <region name=newslist class="list" col=4 row=10 order=desc>abcsadf </region>

需求:提取出每個region的屬性和屬性值,按region分組。

對於這個需求,可以先提取出所有region,再對每個region標籤提取它的屬性和屬性值,但這樣做比較麻煩,可以考慮在一個正則表示式中提取。由於屬性的個數是不固定的,所以不能用固定個數的量詞來匹配屬性對,正則可以寫為

(?is)<region/s+(?:(?<key>[^/s=]+)=(?<value>[^/s>]+)/s*)+>

此時如果還用Groups來取匹配結果時,由於Groups只保留最後一次匹配結果,所以只能取到最後一次匹配成功的子串。這時就要用到Captures屬性。

string test = "<region name=oldslist col=1 row=2 order=asc>abcsadf </region> jfdsajf  <region name=newslist class="list" col=4 row=10 order=desc>abcsadf </region>";

MatchCollection mc = Regex.Matches(test, @"(?is)<region/s+(?:(?<key>[^/s=]+)=(?<value>[^/s>]+)/s*)+>");

for (int i = 0; i < mc.Count; i++)

{

richTextBox2.Text += "第" + (i + 1) + "個region的屬性:/n";

for (int j = 0; j < mc[i].Groups["key"].Captures.Count; j++)

{

richTextBox2.Text += "屬性: " + mc[i].Groups["key"].Captures[j].Value.PadRight(10, ' ') + "  值: " + mc[i].Groups["value"].Captures[j].Value + "/n";

}

richTextBox2.Text += "/n";

}

/*--------輸出--------

第1個region的屬性:

屬性: name        值: oldslist

屬性: col         值: 1

屬性: row         值: 2

屬性: order       值: asc

第2個region的屬性:

屬性: name        值: newslist

屬性: class       值: list

屬性: col         值: 4

屬性: row         值: 10

屬性: order       值: desc

*/

Group實際上是Capture的一個集合,在捕獲組只匹配一個子串時,這個集合只有一個元素,而在捕獲組先後匹配多個子串時,Groups[i].Value只保留最後一個匹配結果,而Capture集合卻可以記錄匹配過程中匹配到的所有子串。

Capture的應用場景並不多,對於上面的例子,如果不使用 Capture,可以通過分次匹配的方式實現,但是在一些複雜的表示式中,很難進行分次匹配,這時Capture就比較有用了。

2.3      替換

替換主要是從源字串中,將符合某一規律或規則的子串替換為其它內容。一般來說,在字串處理中,替換應用也比較廣泛。替換主要是用Replace()方法,在一些替換規則複雜的應用場景中,也可能會用到委託方法。

2.3.1  一般替換

替換的目的很明確,只要找出待替換子串的規律,替換為目標子串就可以了。

舉例1

源字串:<img src="/imgs/logo.jpg"> abc <img src="http://www.test.com/imgs/top.gif">

需求:將相對地址替換為絕對地址,已經是絕對地址的不替換。

string test = "<img src=/"/imgs/logo.jpg/"> abc <img src=/"http://www.test.com/imgs/top.gif/">";

Regex reg = new Regex(@"(?i)(?<=src=(['""]?))(?!http://)(?=[^'""/s>]+/1)");

string result = reg.Replace(test, "http://www.test.com");

/*--------輸出--------

<img src="http://www.test.com/imgs/logo.jpg"> abc <img src="http://www.test.com/imgs/top.gif">

*/

這裡需要說明的是,在.NET中只提供了一個Replace()方法,沒有提供類似於Java中的replaceAll()和replaceFirst()兩種方法,所以如果在.NET中只替換第一次出現的符合規律的子串時,需要在正則表示式中處理。

舉例2

源字串:abc123def123ghi

需求:將第一次出現的“123”替換為空,其餘位置不替換。

string test = "abc123def123ghi";

Regex reg = new Regex(@"(?s)^((?:(?!123).)*)123");

string result = reg.Replace(test, "$1");

/*--------輸出--------

abcdef123ghi

*/

這時用“^”限定只替換第一次出現的子串,由於絕大多數正則引擎都對“^”進行了優化,所以正則表示式在位置0處匹配成功或失敗後,將不再對其它位置進行嘗試匹配。

2.3.2  替換中的委託方法應用

對於一些比較複雜的替換規則,可能會用到委託方法,由於這種應用屬於比較典型的一種應用,所以將在後面的文章中單獨進行介紹。

2.4     分割

分割就是用符合某一規律的子串,將源字串分割成一個數組,主要用到的是Split()方法。由於Regex的Split()方法中,並沒有提供類似於string的Split()方法的StringSplitOptions.RemoveEmptyEntries引數,而如果符合規律的子串出現在開頭或結尾時,會出現不需要的空串,這時需要在正則表示式中進行一下處理。

舉例1

源字串:漢字123文字english

需求:按英文單詞和非英文單詞進行分割(英文單詞包括由a-z,A-Z,0-9,_組成的子串)。

string str = "漢字123文字english";

string[] result = Regex.Split(str, @"(?<!^)/b(?!$)", RegexOptions.ECMAScript);

foreach (string s in result)

{

richTextBox2.Text += s + "/n";

}

/*--------輸出--------

漢字

123

文字

English

*/

這裡分別用“(?<!^)”和“(?!$)”來限定不以開頭或結尾的子串進行分割,結果中也就不會出現不必要的空串了。

還有一些應用,其實可以算作是正則就用技巧範疇的了。

舉例2

源字串:Left(姓名,1),Left(姓名,1) ,  Left    (姓名,1)

需求:以不在“()”內的“,”進行分割。

string test = "Left(姓名,1),Left(姓名,1) ,  Left    (姓名,1)";

Regex reg = new Regex(@"(?<!/([^)]*),(?![^(]*/))");

string[] sArray = reg.Split(test);

foreach (string s in sArray)

{

richTextBox2.Text += s + "/n";

}

/*--------輸出--------

Left(姓名,1)

Left(姓名,1)

Left    (姓名,1)

*/

使用正則的Split()方法時,有一點需求注意,那就是如果正則中出現了捕獲組,那麼捕獲組匹配到的內容也會儲存到分割結果中。

以下舉例不做詳細說明,看下結果基本上就明白了。

string test = "aa11<bbb>cc22<ddd>ee";

string[] temp = Regex.Split(test, @"[0-9]+(<[^>]*>)");

foreach (string s in temp)

{

richTextBox2.Text += s + "/n";

}

/*--------輸出--------

aa

<bbb>

cc

<ddd>

ee

*/

如果不想把捕獲組匹配到的內容也存入結果,可以使用非捕獲組。

string test = "aa11<bbb>cc22<ddd>ee";

string[] temp = Regex.Split(test, @"[0-9]+(?:<[^>]*>)");

foreach (string s in temp)

{

richTextBox2.Text += s + "/n";

}

/*--------輸出--------

aa

cc

ee

*/

3       擴充套件應用

這裡介紹一些可能涉及到的一些.NET中的正則擴充套件應用。

3.1     動態生成正則時的轉義——Escape()

有時需要根據一些變數動態生成正則表示式,這時如果變數中含有正則中的元字元,會被解析成元字元,就可能會導致正則編譯不通過,從而導致程式異常,需要對變數進行轉義處理。Regex. Escape()方法通過替換為轉義碼來轉義最小的字符集(/、*、+、?、|、{、[、(、)、^、$、.、# 和空白)。

比如根據使用者輸入的id取相應的div標籤,id中沒有元字元時,可以取得正確結果。

string test = "<div id=/"test1/">abc</div><div id=/"test2/">def</div>";

string[] ids = new string[] { "test1", "test2" };

foreach (string id in ids)

{

Regex reg = new Regex(@"(?is)<div/s+id=""" + id + @"""[^>]*>(?:(?!</?div/b).)*</div>");

MatchCollection mc = reg.Matches(test);

foreach (Match m in mc)

{

richTextBox2.Text += m.Value + "/n";

}

}

/*--------輸出--------

<div id="test1">abc</div>

<div id="test2">def</div>

*/

但是如果輸入的id中一旦出現未經轉義的元字元,如“abc(”,就會拋類似於下面的異常。

正在分析“(?is)<div/s+id="abc("[^>]*>(?:(?!</?div/b).)*</div>”- ) 不足。

此時可以用Escape()方法對輸入的變數進行轉義處理。

string test = "<div id=/"test1/">abc</div><div id=/"test2/">def</div>";

string[] ids = new string[] { "test1", "test2", "abc(" };

foreach (string id in ids)

{

Regex reg = new Regex(@"(?is)<div/s+id=""" + Regex.Escape(id) + @"""[^>]*>(?:(?!</?div/b).)*</div>");

MatchCollection mc = reg.Matches(test);

foreach (Match m in mc)

{

richTextBox2.Text += m.Value + "/n";

}

}

/*--------輸出--------

<div id="test1">abc</div>

<div id="test2">def</div>

*/

使用Escape()方法轉義後,就可以得到正確的結果,而不會拋異常了。

3.2     靜態方法

.NET中一些Regex類的常見方法都提供了相應的靜態方法,可以不顯式的宣告Regex物件,而直接呼叫相應的方法,書寫起來更方便,程式碼更簡潔、易讀。

比如替換IP地址最後一節為“*”,只需一行程式碼。

string result = Regex.Replace("10.27.123.12", @"/d+$", "*");   //10.27.123.*

靜態方法每次呼叫都會建立一個臨時的Regex物件,使用之後釋放,所以每次呼叫靜態方法時,都會重新編譯,而這將會降低執行效率。因此在迴圈或是頻繁呼叫的方法中,不適合使用靜態方法,而需要進行顯式宣告Regex物件。

但是對於一些只調用一次,或是對執行效率沒有要求的場景下,靜態方法則是很不錯的選擇。

  1. Regex..::.Split(String) 方法與 String..::.Split(array<Char>[]()[]) 方法類似,但前者是在由正則表示式而不是一組字元確定的分隔符處拆分字串。將以儘可能多的次數拆分該字串。如果找不到分隔符,返回值將包含一個值為原始 input 引數字串的元素。
  2. 如果多個匹配項彼此相鄰,則會在陣列中插入空字串。例如,如果用一個連字元來拆分字串,將會導致返回的陣列在兩個相鄰的連字元所在的位置包括一個空字串,如下面的程式碼所示。
  3. Visual Basic  複製程式碼
  4. Dim regex As Regex = New Regex("-")         ' Split on hyphens.
  5. Dim substrings() As String = regex.Split("plum--pear")
  6. For Each match As String In substrings
  7. Console.WriteLine("'{0}'", match)
  8. Next
  9. ' The method writes the following to the console:
  10. '    'plum'
  11. '    ''
  12. '    'pear'
  13. C#  複製程式碼
  14. Regex regex = new Regex("-");         // Split on hyphens.
  15. string[] substrings = regex.Split("plum--pear");
  16. foreach (string match in substrings)
  17. {
  18. Console.WriteLine("'{0}'", match);
  19. }
  20. // The method writes the following to the console:
  21. //    'plum'
  22. //    ''
  23. //    'pear'
  24. 如果將捕獲括號用於 Regex.Split 表示式中,則任何捕獲的文字將包含在生成的字串陣列中。例如,如果要通過在捕獲括號中放入一個連字元的方式來拆分字串“plum-pear”,則會向返回的陣列新增一個包含該連字元的字串元素。
  25. Visual Basic  複製程式碼
  26. Dim regex As Regex = New Regex("(-)")          ' Split on hyphens.
  27. Dim substrings() As String = regex.Split("plum-pear")
  28. For Each match As String In substrings
  29. Console.WriteLine("'{0}'", match)
  30. Next
  31. ' The method writes the following to the console:
  32. '    'plum'
  33. '    '-'
  34. '    'pear'
  35. C#  複製程式碼
  36. Regex regex = new Regex("(-)");         // Split on hyphens.
  37. string[] substrings = regex.Split("plum-pear");
  38. foreach (string match in substrings)
  39. {
  40. Console.WriteLine("'{0}'", match);
  41. }
  42. // The method writes the following to the console:
  43. //    'plum'
  44. //    '-'
  45. //    'pear'
  46. 但是,如果正則表示式模式包含多組捕獲括號,則此方法的行為取決於 .NET Framework 的版本。在 .NET Framework 1.0 和 1.1 版中,如果在第一組捕獲括號中未找到匹配項,則在返回的陣列中不會包含從其他捕獲括號中捕獲的文字。在 .NET Framework 2.0 版中,所有捕獲的文字還新增到返回的陣列中。例如,下面的程式碼使用兩組捕獲括號從日期字串中提取日期元素(包括日期分隔符)。第一組捕獲括號捕獲連字元,而第二組捕獲括號捕獲左斜線。如果已編譯示例程式碼並在 .NET Framework 1.0 或 1.1 中執行,則它不包括斜線;如果已編譯示例程式碼並在 .NET Framework 2.0 中執行,則它包括斜線。
  47. Visual Basic  複製程式碼
  48. Dim input As String = "07/14/2007"
  49. Dim pattern As String = "(-)|(/)"
  50. Dim regex As Regex = New Regex(pattern)
  51. For Each result As String In regex.Split(input)
  52. Console.WriteLine("'{0}'", result)
  53. Next
  54. ' In .NET 1.0 and 1.1, the method returns an array of
  55. ' 3 elements, as follows:
  56. '    '07'
  57. '    '14'
  58. '    '2007'
  59. '
  60. ' In .NET 2.0, the method returns an array of
  61. ' 5 elements, as follows:
  62. '    '07'
  63. '    '/'
  64. '    '14'
  65. '    '/'
  66. '    '2007'
  67. C#  複製程式碼
  68. string input = @"07/14/2007";
  69. string pattern = @"(-)|(/)";
  70. Regex regex = new Regex(pattern);
  71. foreach (string result in regex.Split(input))
  72. {
  73. Console.WriteLine("'{0}'", result);
  74. }
  75. // Under .NET 1.0 and 1.1, the method returns an array of
  76. // 3 elements, as follows:
  77. //    '07'
  78. //    '14'
  79. //    '2007'
  80. //
  81. // Under .NET 2.0, the method returns an array of
  82. // 5 elements, as follows:
  83. //    '07'
  84. //    '/'
  85. //    '14'
  86. //    '/'
  87. //    '2007'
  88. 如果正則表示式可以匹配空字串,則 Split(String) 會將字串拆分為由單字元組成的字串的陣列,因為每個位置都有空字串分隔符。例如:
  89. Visual Basic  複製程式碼
  90. Dim input As String = "characters"
  91. Dim regex As New Regex("")
  92. Dim substrings() As String = regex.Split(input)
  93. Console.Write("{")
  94. For ctr As Integer = 0 to substrings.Length - 1
  95. Console.Write(substrings(ctr))
  96. If ctr < substrings.Length - 1 Then Console.Write(", ")
  97. Next
  98. Console.WriteLine("}")
  99. ' The example produces the following output:
  100. '    {, c, h, a, r, a, c, t, e, r, s, }
  101. C#  複製程式碼
  102. string input = "characters";
  103. Regex regex = new Regex("");
  104. string[] substrings = regex.Split(input);
  105. Console.Write("{");
  106. for(int ctr = 0; ctr < substrings.Length; ctr++)
  107. {
  108. Console.Write(substrings[ctr]);
  109. if (ctr < substrings.Length - 1)
  110. Console.Write(", ");
  111. }
  112. Console.WriteLine("}");
  113. // The example produces the following output:
  114. //    {, c, h, a, r, a, c, t, e, r, s, }
  115. 請注意,返回陣列的開頭和結尾還包括空字串。