【转】C# 正则表达式 使用介绍
正則元字符
在說正則表達(dá)式之前我們先來看看通配符,我想通配符大家都用過。通配符主要有星號(*)和問號(?),用來模糊搜索文件。winodws中我們常會(huì)使用搜索來查找一些文件。如:*.jpg,XXX.docx的方式,來快速查找文件。其實(shí)正則表達(dá)式和我們通配符很相似也是通過特定的字符匹配我們所要查詢的內(nèi)容信息。已下代碼都是區(qū)分大小寫。
常用元字符
?
| 代碼 | 說明 |
| . ? ? ? ? ? ? ? ? ? ?? | 匹配除換行符以外的任意字符。 |
| \w | 匹配字母或數(shù)字或下劃線或漢字。 |
| \s? | 匹配任意的空白符。 |
| \d | 匹配數(shù)字。 |
| \b | 匹配單詞的開始或結(jié)束。 |
| [ck] | 匹配包含括號內(nèi)元素的字符 |
| ^ | 匹配行的開始。 |
| $? | 匹配行的結(jié)束。 |
| \ | 對下一個(gè)字符轉(zhuǎn)義。比如$是個(gè)特殊的字符。要匹配$的話就得用\$ |
| | | 分支條件,如:x|y匹配 x 或 y。 |
?
反義元字符
?
| 代碼 | 說明 |
| \W ? ? ? ? ? ?? | 匹配任意不是字母,數(shù)字,下劃線,漢字的字符。 |
| \S | 匹配任意不是空白符的字符。等價(jià)于 [^ \f\n\r\t\v]。 |
| \D | 匹配任意非數(shù)字的字符。等價(jià)于 [^0-9]。 |
| \B | 匹配不是單詞開頭或結(jié)束的位置。 |
| [^CK]? | 匹配除了CK以外的任意字符。 |
?
特殊元字符
?
| 代碼 | 說明 |
| \f ? ? ? ? ? ? | 匹配一個(gè)換頁符。等價(jià)于 \x0c 和 \cL。 |
| \n | 匹配一個(gè)換行符。等價(jià)于 \x0a 和 \cJ。 |
| \r | 匹配一個(gè)回車符。等價(jià)于 \x0d 和 \cM。 |
| \t | 匹配一個(gè)制表符。等價(jià)于 \x09 和 \cI。 |
| \v | 匹配一個(gè)垂直制表符。等價(jià)于 \x0b 和 \cK。 |
?
限定符
?
| 代碼 | 說明 |
| * ? ? ? ? ? ? ? ? ? ? ? | 匹配前面的子表達(dá)式零次或多次。 |
| + | 匹配前面的子表達(dá)式一次或多次。 |
| ? | 匹配前面的子表達(dá)式零次或一次。 |
| {n} | n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。 |
| {n,} | n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次。 |
| {n,m} | m 和 n 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。 |
?
懶惰限定符
?
| 代碼 | 說明 |
| *? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 重復(fù)任意次,但盡可能少重復(fù)。 如 "acbacb" ?正則 ?"a.*?b" 只會(huì)取到第一個(gè)"acb" 原本可以全部取到但加了限定符后,只會(huì)匹配盡可能少的字符 ,而"acbacb"最少字符的結(jié)果就是"acb" 。 |
| +? | 重復(fù)1次或更多次,但盡可能少重復(fù)。與上面一樣,只是至少要重復(fù)1次。 |
| ?? | 重復(fù)0次或1次,但盡可能少重復(fù)。 如 "aaacb" 正則 "a.??b" 只會(huì)取到最后的三個(gè)字符"acb"。 |
| {n,m}? | 重復(fù)n到m次,但盡可能少重復(fù)。 如 "aaaaaaaa" ?正則 "a{0,m}" 因?yàn)樽钌偈?次所以取到結(jié)果為空。 |
| {n,}? | 重復(fù)n次以上,但盡可能少重復(fù)。 如 "aaaaaaa" ?正則 "a{1,}" 最少是1次所以取到結(jié)果為 "a"。 |
?
捕獲分組
?
| 代碼 | 說明 |
| (exp) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? | 匹配exp,并捕獲文本到自動(dòng)命名的組里。 |
| (?<name>exp) | 匹配exp,并捕獲文本到名稱為name的組里。 |
| (?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號以下為零寬斷言。 |
| (?=exp) | 匹配exp前面的位置。 如 "How are you doing" 正則"(?<txt>.+(?=ing))" 這里取ing前所有的字符,并定義了一個(gè)捕獲分組名字為 "txt" 而"txt"這個(gè)組里的值為"How are you do"; |
| (?<=exp) | 匹配exp后面的位置。 如 "How are you doing" 正則"(?<txt>(?<=How).+)" 這里取"How"之后所有的字符,并定義了一個(gè)捕獲分組名字為 "txt" 而"txt"這個(gè)組里的值為" are you doing"; |
| (?!exp) | 匹配后面跟的不是exp的位置。 如 "123abc" 正則 "\d{3}(?!\d)"匹配3位數(shù)字后非數(shù)字的結(jié)果 |
| (?<!exp) | 匹配前面不是exp的位置。 如 "abc123 " 正則 "(?<![0-9])123" 匹配"123"前面是非數(shù)字的結(jié)果也可寫成"(?!<\d)123" |
?
得到上面秘籍后我們可以小試牛刀...
小試牛刀
在C#中使用正則表達(dá)式主要是通過Regex類來實(shí)現(xiàn)。命名空間:using System.Text.RegularExpressions。
其中常用方法:
?
| 名稱 | 說明 |
| IsMatch(String, String) | 指示?Regex?構(gòu)造函數(shù)中指定的正則表達(dá)式在指定的輸入字符串中是否找到了匹配項(xiàng)。 |
| Match(String, String) | 在指定的輸入字符串中搜索?Regex?構(gòu)造函數(shù)中指定的正則表達(dá)式的第一個(gè)匹配項(xiàng)。 |
| Matches(String, String) | 在指定的輸入字符串中搜索正則表達(dá)式的所有匹配項(xiàng)。 |
| Replace(String, String) | 在指定的輸入字符串內(nèi),使用指定的替換字符串替換與某個(gè)正則表達(dá)式模式匹配的所有字符串。 |
| Split(String, String) | 在由?Regex?構(gòu)造函數(shù)指定的正則表達(dá)式模式所定義的位置,拆分指定的輸入字符串。 |
?
在使用正則表達(dá)式前我們先來看看“@”符號的使用。
學(xué)過C#的人都知道C# 中字符串常量可以以@ 開頭聲名,這樣的優(yōu)點(diǎn)是轉(zhuǎn)義序列“不”被處理,按“原樣”輸出,即我們不需要對轉(zhuǎn)義字符加上 \ (反斜扛),就可以輕松coding。如:
?
復(fù)制代碼 代碼如下:string filePath = @"c:\Docs\Source\CK.txt" // rather than "c:\\Docs\\Source\\CK.txt"
?
如要在一個(gè)用 @ 引起來的字符串中包括一個(gè)雙引號,就需要使用兩對雙引號了。這時(shí)候你不能使用 \ 來轉(zhuǎn)義爽引號了,因?yàn)樵谶@里 \ 的轉(zhuǎn)義用途已經(jīng)被 @ “屏蔽”掉了。如:
?
復(fù)制代碼 代碼如下:string str=@"""Ahoy!"" cried the captain." // 輸出為: "Ahoy!" cried the captain.
?
字符串匹配:
在實(shí)際項(xiàng)目中我們常常需要對用戶輸入的信息進(jìn)行驗(yàn)證。如:匹配用戶輸入的內(nèi)容是否為數(shù)字,是否為有效的手機(jī)號碼,郵箱是否合法....等。
實(shí)例代碼:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | string RegexStr = string.Empty; #region 字符串匹配 RegexStr = "^[0-9]+$"; //匹配字符串的開始和結(jié)束是否為0-9的數(shù)字[定位字符] Console.WriteLine("判斷'R1123'是否為數(shù)字:{0}", Regex.IsMatch("R1123", RegexStr)); Console.WriteLine("判斷'1123'是否為數(shù)字:{0}", Regex.IsMatch("1123", RegexStr)); RegexStr = @"\d+"; //匹配字符串中間是否包含數(shù)字(這里沒有從開始進(jìn)行匹配噢,任意位子只要有一個(gè)數(shù)字即可) Console.WriteLine("'R1123'是否包含數(shù)字:{0}", Regex.IsMatch("R1123", RegexStr)); Console.WriteLine("'博客園'是否包含數(shù)字:{0}", Regex.IsMatch("博客園", RegexStr)); //感謝@zhoumy的提醒..已修改錯(cuò)誤代碼 RegexStr = @"^Hello World[\w\W]*"; //已Hello World開頭的任意字符(\w\W:組合可匹配任意字符) Console.WriteLine("'HeLLO WORLD xx hh xx'是否已Hello World開頭:{0}", Regex.IsMatch("HeLLO WORLD xx hh xx", RegexStr, RegexOptions.IgnoreCase)); Console.WriteLine("'LLO WORLD xx hh xx'是否已Hello World開頭:{0}", Regex.IsMatch("LLO WORLD xx hh xx", RegexStr,RegexOptions.IgnoreCase)); //RegexOptions.IgnoreCase:指定不區(qū)分大小寫的匹配。 #endregion |
顯示結(jié)果:
字符串查找:
實(shí)例代碼:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | string RegexStr = string.Empty; #region 字符串查找 string LinkA = "<a href=\"http://www.baidu.com\" target=\"_blank\">百度</a>"; RegexStr = @"href=""[\S]+"""; // ""匹配" Match mt = Regex.Match(LinkA, RegexStr); Console.WriteLine("{0}。", LinkA); Console.WriteLine("獲得href中的值:{0}。", mt.Value); RegexStr = @"<h[^23456]>[\S]+<h[1]>"; //<h[^23456]>:匹配h除了2,3,4,5,6之中的值,<h[1]>:h匹配包含括號內(nèi)元素的字符 Console.WriteLine("{0}。GetH1值:{1}", "<H1>標(biāo)題<H1>", Regex.Match("<H1>標(biāo)題<H1>", RegexStr, RegexOptions.IgnoreCase).Value); Console.WriteLine("{0}。GetH1值:{1}", "<h2>小標(biāo)<h2>", Regex.Match("<h2>小標(biāo)<h2>", RegexStr, RegexOptions.IgnoreCase).Value); //RegexOptions.IgnoreCase:指定不區(qū)分大小寫的匹配。 RegexStr = @"ab\w+|ij\w{1,}"; //匹配ab和字母 或 ij和字母 Console.WriteLine("{0}。多選結(jié)構(gòu):{1}", "abcd", Regex.Match("abcd", RegexStr).Value); Console.WriteLine("{0}。多選結(jié)構(gòu):{1}", "efgh", Regex.Match("efgh", RegexStr).Value); Console.WriteLine("{0}。多選結(jié)構(gòu):{1}", "ijk", Regex.Match("ijk", RegexStr).Value); RegexStr = @"張三?豐"; //?匹配前面的子表達(dá)式零次或一次。 Console.WriteLine("{0}。可選項(xiàng)元素:{1}", "張三豐", Regex.Match("張三豐", RegexStr).Value); Console.WriteLine("{0}。可選項(xiàng)元素:{1}", "張豐", Regex.Match("張豐", RegexStr).Value); Console.WriteLine("{0}??蛇x項(xiàng)元素:{1}", "張飛", Regex.Match("張飛", RegexStr).Value); /* ?例如: July|Jul 可縮短為 July? 4th|4 可縮短為 4(th)? */ //匹配特殊字符 RegexStr = @"Asp\.net"; //匹配Asp.net字符,因?yàn)?是元字符他會(huì)匹配除換行符以外的任意字符。這里我們只需要他匹配.字符即可。所以需要轉(zhuǎn)義\.這樣表示匹配.字符 Console.WriteLine("{0}。匹配Asp.net字符:{1}", "Java Asp.net SQLServer", Regex.Match("Java Asp.net SQLServer", RegexStr).Value); Console.WriteLine("{0}。匹配Asp.net字符:{1}", "C# Java", Regex.Match("C# Java", RegexStr).Value); #endregion |
顯示結(jié)果:
?
?
貪婪與懶惰
?| 1 2 3 4 5 6 7 8 9 10 | string f = "fooot"; //貪婪匹配 RegexStr = @"f[o]+"; Match m1 = Regex.Match(f, RegexStr); Console.WriteLine("{0}貪婪匹配(匹配盡可能多的字符):{1}", f, m1.ToString()); //懶惰匹配 RegexStr = @"f[o]+?"; Match m2 = Regex.Match(f, RegexStr); Console.WriteLine("{0}懶惰匹配(匹配盡可能少重復(fù)):{1}", f, m2.ToString()); |
顯示結(jié)果:
從上面的例子中我們不難看出貪婪與懶惰的區(qū)別,他們的名子取的都很形象。
貪婪匹配:匹配盡可能多的字符。
懶惰匹配:匹配盡可能少的字符。
(exp)分組
在做爬蟲時(shí)我們經(jīng)常獲得A中一些有用信息。如href,title和顯示內(nèi)容等。
?| 1 2 3 4 5 6 7 | string TaobaoLink = "<a href=\"http://www.taobao.com\" title=\"淘寶網(wǎng) - 淘!我喜歡\" target=\"_blank\">淘寶</a>"; RegexStr = @"<a[^>]+href=""(\S+)""[^>]+title=""([\s\S]+?)""[^>]+>(\S+)</a>"; Match mat = Regex.Match(TaobaoLink, RegexStr); for (int i = 0; i < mat.Groups.Count; i++) { ?Console.WriteLine("第"+i+"組:"+mat.Groups[i].Value); } |
顯示結(jié)果:
在正則表達(dá)式里使用()包含的文本自動(dòng)會(huì)命名為一個(gè)組。上面的表達(dá)式中共使用了4個(gè)()可以認(rèn)為是分為了4組。
輸出結(jié)果共分為:4組。
0組:為我們所匹配的字符串。
1組:是我們第一個(gè)括號[href=""(\S+)""]中(\S+)所匹配的網(wǎng)址信息。內(nèi)容為:http://www.taobao.com。
2組:是第二個(gè)括號[title=""([\s\S]+?)""]中所匹配的內(nèi)容信息。內(nèi)容為:淘寶網(wǎng) - 淘!我喜歡。
這里我們會(huì)看到+?懶惰限定符。title=""([\s\S]+?)"" 這里+?的下一個(gè)字符為"雙引號,"雙引號在匹配字符串后面還有三個(gè)。+?懶惰限定符會(huì)盡可能少重復(fù),所他會(huì)匹配最前面那個(gè)"雙引號。如果我們不使用+?懶惰限定符他會(huì)匹配到:淘寶網(wǎng) - 淘!我喜歡" target= 會(huì)盡可能多重復(fù)匹配。
3組:是第三個(gè)括號[(\S+)]所匹配的內(nèi)容信息。內(nèi)容為:淘寶。
說明:反義元字符所對應(yīng)的元字符都能組合匹配任意字符。如:[\w\W],[\s\S],[\d\D]..
(?<name>exp) 分組取名
當(dāng)我們匹配分組信息過多后,在某種場合只需取當(dāng)中某幾組信息。這時(shí)我們可以對分組取名。通過分組名稱來快速提取對應(yīng)信息。
?| 1 2 3 4 | string Resume = "基本信息姓名:CK|求職意向:.NET軟件工程師|性別:男|學(xué)歷:本專|出生日期:1988-08-08|戶籍:湖北.孝感|E - Mail:9245162@qq.com|手機(jī):15000000000"; RegexStr = @"姓名:(?<name>[\S]+)\|\S+性別:(?<sex>[\S]{1})\|學(xué)歷:(?<xueli>[\S]{1,10})\|出生日期:(?<Birth>[\S]{10})\|[\s\S]+手機(jī):(?<phone>[\d]{11})"; Match matc = Regex.Match(Resume, RegexStr); Console.WriteLine("姓名:{0},手機(jī)號:{1}", matc.Groups["name"].ToString(), matc.Groups["phone"].ToString()); |
顯示結(jié)果:
通過(?<name>exp)可以很輕易為分組取名。然后通過Groups["name"]取得分組值。
獲得頁面中A標(biāo)簽中href值
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | string PageInfo = @"<hteml> ??????<div id=""div1""> ???????<a href=""http://www.baidu.con"" target=""_blank"">百度</a> ???????<a href=""http://www.taobao.con"" target=""_blank"">淘寶</a> ???????<a href=""http://www.cnblogs.com"" target=""_blank"">博客園</a> ???????<a href=""http://www.google.con"" target=""_blank"">google</a> ??????</div> ??????<div id=""div2""> ???????<a href=""/zufang/"">整租</a> ???????<a href=""/hezu/"">合租</a> ???????<a href=""/qiuzu/"">求租</a> ???????<a href=""/ershoufang/"">二手房</a> ???????<a href=""/shangpucz/"">商鋪出租</a> ??????</div> ?????</hteml>"; RegexStr = @"<a[^>]+href=""(?<href>[\S]+?)""[^>]*>(?<text>[\S]+?)</a>"; MatchCollection mc = Regex.Matches(PageInfo, RegexStr); foreach (Match item in mc) { ?Console.WriteLine("href:{0}--->text:{1}",item.Groups["href"].ToString(),item.Groups["text"].ToString()); } |
顯示結(jié)果:
Replace 替換字符串
用戶在輸入信息時(shí)偶爾會(huì)包含一些敏感詞,這時(shí)我們需要替換這個(gè)敏感詞。
?| 1 2 3 4 5 | string PageInputStr = "靠.TMMD,今天真不爽...."; RegexStr = @"靠|TMMD|媽的"; Regex rep_regex = new Regex(RegexStr); Console.WriteLine("用戶輸入信息:{0}", PageInputStr); Console.WriteLine("頁面顯示信息:{0}", rep_regex.Replace(PageInputStr, "***")); |
顯示結(jié)果:
對一些敏感詞直接替換成***代替。
?
Split 拆分字符串
?| 1 2 3 4 5 6 7 8 | string SplitInputStr = "1xxxxx.2ooooo.3eeee.4kkkkkk."; RegexStr = @"\d"; Regex spl_regex = new Regex(RegexStr); string[] str = spl_regex.Split(SplitInputStr); foreach (string item in str) { ?Console.WriteLine(item); } |
顯示結(jié)果:
根據(jù)數(shù)字截取字符串。
首先,我們先看幾個(gè)實(shí)際的例子:?
1.????驗(yàn)證輸入字符是否
javascript:
var?ex?=?"^\\w+$";
var?re?=?new?RegExp(ex,"i");
return?re.test(str);
?????????VBScript
Dim?regEx,flag,ex
ex?=?"^\w+$"
Set?regEx?=?New?RegExp
regEx.IgnoreCase?=?True?
regEx.Global?=?True?
regEx.Pattern?=?ex
flag?=?regEx.Test(?str?)
??????????????C#
System.String?ex?=?@"^\w+$";
??????????????System.Text.RegularExpressions.Regex?reg?=?new?Regex(?ex?);???????????????????????????
??????????????bool?flag?=?reg.IsMatch(?str?);
2.????驗(yàn)證郵件格式
C#
System.String?ex?=?@"^\w+@\w+\.\w+$";
System.Text.RegularExpressions.Regex?reg?=?new?Regex(?ex?);
bool?flag?=?reg.IsMatch(?str?);
3.????更改日期的格式(用?dd-mm-yy?的日期形式代替?mm/dd/yy?的日期形式)
C#
String?MDYToDMY(String?input)?
???{
??????return?Regex.Replace(input,?
?????????"\\b(?\\d{1,2})/(?\\d{1,2})/(?\\d{2,4})\\b",
?????????"${day}-${month}-${year}");
???}
4.????從?URL?提取協(xié)議和端口號
C#
String?Extension(String?url)?
???{
??????Regex?r?=?new?Regex(@"^(?\w+)://[^/]+?(?:\d+)?/",
?????????RegexOptions.Compiled);
??????return?r.Match(url).Result("${proto}${port}");?
???}
這里的例子可能是我們在網(wǎng)頁開發(fā)中,通常會(huì)碰到的一些正則表達(dá)式,尤其在第一個(gè)例子中,給出了使用javascript,vbScript,C#等不同語言的實(shí)現(xiàn)方式,大家不難看出,對于不同的語言來說,正則表達(dá)式?jīng)]有區(qū)別,只是正則表達(dá)式的實(shí)現(xiàn)類不同而已。而如何發(fā)揮正則表達(dá)式的公用,也要看實(shí)現(xiàn)類的支持。
(摘自msdn:?Microsoft?.NET?框架?SDK?提供大量的正則表達(dá)式工具,使您能夠高效地創(chuàng)建、比較和修改字符串,以及迅速地分析大量文本和數(shù)據(jù)以搜索、移除和替換文本模式。ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpconregularexpressionslanguageelements.htm)
下面我們逐個(gè)來分析這些例子:
1-2,這兩個(gè)例子很簡單,只是簡單的驗(yàn)證字符串是否符合正則表達(dá)式規(guī)定的格式,其中使用的語法,在第一篇文章中都已經(jīng)介紹過了,這里做一下簡單的描述。
第1個(gè)例子的表達(dá)式:??^\w+$
^?--?表示限定匹配開始于字符串的開始
?????????\w?–?表示匹配英文字符
?????????+?--?表示匹配字符出現(xiàn)1次或多次
?????????$?--?表示匹配字符到字符串結(jié)尾處結(jié)束
?????????驗(yàn)證形如asgasdfs的字符串
第2個(gè)例子的表達(dá)式:??^\w+@\w+.\w+$
^?--?表示限定匹配開始于字符串的開始
\w?–?表示匹配英文字符
+?--?表示匹配字符出現(xiàn)1次或多次
@?--?匹配普通字符@
\.?–?匹配普通字符.(注意.為特殊字符,因此要加上\轉(zhuǎn)譯)
$?--?表示匹配字符到字符串結(jié)尾處結(jié)束
驗(yàn)證形如dragontt@sina.com的郵件格式
?
?
?????第3?個(gè)例子中,使用了替換,因此,我們還是先來看看正則表達(dá)式中替換的定義:
(ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpconsubstitutions.htm)
替換
字符
?含義
?
$123
?替換由組號?123(十進(jìn)制)匹配的最后一個(gè)子字符串。
?
${name}
?替換由?(??)?組匹配的最后一個(gè)子字符串。
?
$$
?替換單個(gè)“$”字符。
?
$&
?替換完全匹配本身的一個(gè)副本。
?
$`
?替換匹配前的輸入字符串的所有文本。
?
$'
?替換匹配后的輸入字符串的所有文本。
?
$+
?替換最后捕獲的組。
?
$_
?替換整個(gè)輸入字符串。
?
分組構(gòu)造
(ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpcongroupingconstructs.htm)
分組構(gòu)造
?定義
?
(?)
?捕獲匹配的子字符串(或非捕獲組;有關(guān)更多信息,請參閱正則表達(dá)式選項(xiàng)中的?ExplicitCapture?選項(xiàng)。)使用?()?的捕獲根據(jù)左括號的順序從?1?開始自動(dòng)編號。捕獲元素編號為零的第一個(gè)捕獲是由整個(gè)正則表達(dá)式模式匹配的文本。
?
(?<name>?)
?將匹配的子字符串捕獲到一個(gè)組名稱或編號名稱中。用于?name?的字符串不能包含任何標(biāo)點(diǎn)符號,并且不能以數(shù)字開頭??梢允褂脝我柼娲饫ㄌ?#xff0c;例如?(?'name')。
?
(?<name1-name2>?)
?平衡組定義。刪除先前定義的?name2?組的定義并在?name1?組中存儲(chǔ)先前定義的?name2?組和當(dāng)前組之間的間隔。如果未定義?name2?組,則匹配將回溯。由于刪除?name2?的最后一個(gè)定義會(huì)顯示?name2?的先前定義,因此該構(gòu)造允許將?name2?組的捕獲堆棧用作計(jì)數(shù)器以跟蹤嵌套構(gòu)造(如括號)。在此構(gòu)造中,name1?是可選的。可以使用單引號替代尖括號,例如?(?'name1-name2')。
?
(?:?)
?非捕獲組。
?
(?imnsx-imnsx:?)
?應(yīng)用或禁用子表達(dá)式中指定的選項(xiàng)。例如,(?i-s:?)?將打開不區(qū)分大小寫并禁用單行模式。有關(guān)更多信息,請參閱正則表達(dá)式選項(xiàng)。
?
(?=?)
?零寬度正預(yù)測先行斷言。僅當(dāng)子表達(dá)式在此位置的右側(cè)匹配時(shí)才繼續(xù)匹配。例如,\w+(?=\d)?與后跟數(shù)字的單詞匹配,而不與該數(shù)字匹配。此構(gòu)造不會(huì)回溯。
?
(?!?)
?零寬度負(fù)預(yù)測先行斷言。僅當(dāng)子表達(dá)式不在此位置的右側(cè)匹配時(shí)才繼續(xù)匹配。例如,\b(?!un)\w+\b?與不以?un?開頭的單詞匹配。
?
(?<=?)
?零寬度正回顧后發(fā)斷言。僅當(dāng)子表達(dá)式在此位置的左側(cè)匹配時(shí)才繼續(xù)匹配。例如,(?<=19)99?與跟在?19?后面的?99?的實(shí)例匹配。此構(gòu)造不會(huì)回溯。
?
(?
?零寬度負(fù)回顧后發(fā)斷言。僅當(dāng)子表達(dá)式不在此位置的左側(cè)匹配時(shí)才繼續(xù)匹配。
?
(?>?)
?非回溯子表達(dá)式(也稱為貪婪子表達(dá)式)。該子表達(dá)式僅完全匹配一次,然后就不會(huì)逐段參與回溯了。(也就是說,該子表達(dá)式僅與可由該子表達(dá)式單獨(dú)匹配的字符串匹配。)
?
?
我們還是先簡單的了解一下這兩個(gè)概念:
分組構(gòu)造:
最基本的構(gòu)造方式就是(),在左右括號中括起來的部分,就是一個(gè)分組;
更進(jìn)一步的分組就是形如:(?<name>?)的分組方式,這種方式與第一種方式的不同點(diǎn),就是對分組的部分進(jìn)行了命名,這樣就可以通過該組的命名來獲取信息;
(還有形如(?=?)等等的分組構(gòu)造,我們這篇的例子中也沒有使用到,下次我們在來介紹)
替換:
???????上面提到了兩種基本的構(gòu)造分組方式()以及(?<name>?),通過這兩種分組方式,我們可以得到形如$1,${name}的匹配結(jié)果。
?
???????這樣說,可能概念上還是有些模糊,我們還是結(jié)合上面的例子來說:
第三個(gè)例子的正則表達(dá)式為:\\b(?\\d{1,2})/(?\\d{1,2})/(?\\d{2,4})\\b
(解釋一下,為什么這里都是\\一起用:這里是C#的例子,在C#語言中\(zhòng)是轉(zhuǎn)譯字符,要想字符串中的\不轉(zhuǎn)譯,就需要使用\\或者在整個(gè)字符串的開始加上@標(biāo)記,即上面等價(jià)與
@”\b(?\d{1,2})/(?\d{1,2})/(?\d{2,4}\b”)
\b?--??是一種特殊情況。在正則表達(dá)式中,除了在?[]?字符類中表示退格符以外,\b?表示字邊界(在?\w?和?\W?字符之間)。在替換模式中,\b?始終表示退格符
(?\d{1,2})?–?構(gòu)造一個(gè)名為month的分組,這個(gè)分組匹配一個(gè)長度為1-2的數(shù)字
/?--?匹配普通的/字符
(?\d{1,2})?--構(gòu)造一個(gè)名為day的分組,這個(gè)分組匹配一個(gè)長度為1-2的數(shù)字
/?--?匹配普通的/字符
(?\d{2,4}\b”)?--構(gòu)造一個(gè)名為year的分組,這個(gè)分組匹配一個(gè)長度為2-4的數(shù)字
?
這里還不能夠看出這些分組的作用,我們接著看這一句
${day}-${month}-${year}
${day}?–?獲得上面構(gòu)造的名為day的分組匹配后的信息
-?--?普通的-字符
${month}?--獲得上面構(gòu)造的名為month的分組匹配后的信息
-?--?普通的-字符
${year}?--獲得上面構(gòu)造的名為year的分組匹配后的信息
?
舉例來說:
將形如04/02/2003的日期使用例3種的方法替換
(?\d{1,2})?分組將匹配到04由${month}得到這個(gè)匹配值
(?\d{1,2})?分組將匹配到02由${day}得到這個(gè)匹配值
(?\d{1,2})?分組將匹配到2003由${year}得到這個(gè)匹配值
了解了這個(gè)例子后,我們在來看第4個(gè)例子就很簡單了。
?
第4個(gè)例子的正則
^(?\w+)://[^/]+?(?:\d+)?/
^?--?表示限定匹配開始于字符串的開始
(?\w+)?–?構(gòu)造一個(gè)名為proto的分組,匹配一個(gè)或多個(gè)字母
:?--?普通的:字符
//?--?匹配兩個(gè)/字符
[^/]?–?表示這里不允許是/字符
+??–?表示指定盡可能少地使用重復(fù)但至少使用一次匹配
(?:\d+)?–?構(gòu)造一個(gè)名為port的分組,匹配形如:2134(冒號+一個(gè)或多個(gè)數(shù)字)
??–?表示匹配字符出現(xiàn)0次或1次
/?--?匹配/字符
?
最后通過${proto}${port}來獲取兩個(gè)分組構(gòu)造的匹配內(nèi)容
總結(jié)
以上是生活随笔為你收集整理的【转】C# 正则表达式 使用介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。