初學正則時,對于Regex類不熟悉,遇到問題不知道該用哪種方法解決,本文結合一些正則應用的典型應用場景,介紹一下Regex類的基本應用。這里重點進行.NET類的介紹,對于正則的運用,不做深入探討。
正則的應用最終都是進行模式的匹配,而根據目的的不同,基本上可以分為以下幾種應用:驗證、提取、替換、分割。結合.NET提供的控件、類以及類的方法,可以很方便的實現這些應用。
以下將結合一些典型的應用場景,對.NET中常見的類、方法及屬性進行介紹。本文旨在.NET類基礎用法的引導,對于其中涉及到的正則表達式不做深入探討。本文適合于在.NET平臺下使用正則的初學者。
驗證的目的是為了判斷輸入的源字符串是否符合某一規律或規則,根據需求的不同,可能是校驗整個源字符串,也可能只是校驗其中一個子串。
驗證在.NET中一般有兩種應用,一種是在驗證控件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代碼來實現,也是很簡單的。
程序中的校驗基本上就是使用IsMatch方法,驗證的對象可能是源字符串的整體,也可能只是其中一個子串。
驗證源字符串的整體是否符合某一規則,與使用RegularExpressionValidator時的需求基本上一致,不過由于是在.NET程序中,所以使用的是.NET的語法,比JavaScript中要強大得多。比如驗證一個文本框輸入的字符串是否符合某一規則,就是一個典型的驗證整體的需求。
舉例1:驗證textBox1輸入內容,要求整數部分為0或正整數,小數可有可無,有小數時必須為2位。
Regexreg =newRegex(@"^(?:[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 =newstring[] {"1985aaa1985bb","bcae1958fiefadf1955fef","atijc1944cvkd","df2564isdjfef2564d","abc1234def5678ghi5678jkl"};
Regexreg =newRegex(@"(/d{4})(?:(?!/1).)*/1");
foreach(stringsintest)
{
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 =newstring[] {"1985aaa1985bb","bcae1958fiefadf1955fef","atijc1944cvkd","df2564isdjfef2564d","abc1234def5678ghi5678jkl"};
Regexreg =newRegex(@"^(?:(?!/d{4}).)*(/d{4})(?:(?!/1).)*/1");
foreach(stringsintest)
{
richTextBox2.Text +="源字符串:"+ s.PadRight(25,' ') +"驗證結果:"+ reg.IsMatch(s) +"/n";
}
/*--------輸出--------
源字符串:1985aaa1985bb驗證結果:True
源字符串:bcae1958fiefadf1955fef驗證結果:False
源字符串:atijc1944cvkd驗證結果:False
源字符串:df2564isdjfef2564d驗證結果:True
源字符串:abc1234def5678ghi5678jkl驗證結果:False
*/
提取主要是從源字符串中,取得一個或多個符合某一規律或規則的子串。一般來說,在字符串處理中,提取應用比較廣泛。提取時用得比較多的是Match()和Matches()方法,以及結果處理時Match類和MatchCollection類的一些方法,有時也會用到Capture類的一些方法。
當需要提取的內容只有一個,或是只需要獲取第一次成功匹配的內容時,可以使用Match()方法。當使用Match()方法時,只要在某一位置匹配成功,就不再繼續嘗試匹配,并返回一個Match類型的對象。
舉例:提取姓名
源字符串:姓名:張三,性別:男,年齡:25
代碼實現:
stringtest ="姓名:張三,性別:男,年齡:25";
Regexreg =newRegex(@"(?<=姓名:)[^,]+");
Matchm = reg.Match(test);
if(m.Success)//驗證是否匹配成功
{
richTextBox2.Text = m.Value;
}
/*--------輸出--------
張三
*/
雖然Match()只是取一次匹配,但是可以通過捕獲組來獲取多個指定子串,比如獲取第一個<a…>標簽的鏈接和文本。
stringtest ="abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";
Regexreg =newRegex(@"(?is)<a(?:(?!href=).)href=(['""]?)(?<url>[^""/s>]*)/1[^>]*>(?<text>(?:(?!</?a/b).)*)</a>");
Matchm = reg.Match(test);
if(m.Success)
{
richTextBox2.Text += m.Groups["url"].Value +"/n";//鏈接
richTextBox2.Text += m.Groups["text"].Value +"/n";//文本
}
/*--------輸出--------
www.test1.com
測試一
*/
對于捕獲組捕獲結果的引用,還有一種方式
stringtest ="abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";
Regexreg =newRegex(@"(?is)<a(?:(?!href=).)href=(['""]?)(?<url>[^""/s>]*)/1[^>]*>(?<text>(?:(?!</?a/b).)*)</a>");Matchm = reg.Match(test);
if(m.Success)
{
richTextBox2.Text += m.Result("${url}") +"/n";//鏈接
richTextBox2.Text += m.Result("${text}") +"/n";//文本
}
/*--------輸出--------
www.test1.com
測試一
*/
這兩種方法獲取的結果都是一樣的,使用哪一種,通常根據個人習慣而定。
當需要提取的內容有多個,并且需要提取所有符合規律的子串時,可以使用Matches()方法。當使用Matches()方法時,需要遍歷源字符串的每一個位置進行嘗試匹配,匹配結束返回一個MatchCollection類型的對象。
對于1.2.1節提到的提取鏈接和文本的例子,如果提取的是全部鏈接和文本,而不僅僅是第一個時,可以使用Matches()方法。
stringtest ="abc<a href=/"www.test1.com/">測試一</a>def<a href=/"www.test2.com/">測試二</a>ghi";
Regexreg =newRegex(@"(?is)<a(
新聞熱點
疑難解答