說到正則表達式,大家就會想到那像火星文一樣的正則表達式字元串。雖然看起來很奇怪,但是一個個都搞清楚那些東西分別表示什麼意思的時候,會發現這東西其實也不難。說乾就乾,我們來一個個的理解。 先弄點數據 先來個最簡單的開個味,太深了都沒有興趣往下看了 沒有任何的正則表達式的元字元(也就是保留字),http ...
說到正則表達式,大家就會想到那像火星文一樣的正則表達式字元串。雖然看起來很奇怪,但是一個個都搞清楚那些東西分別表示什麼意思的時候,會發現這東西其實也不難。說乾就乾,我們來一個個的理解。
先弄點數據
string input = "http://www.tansea.cn/23 233【個人博客】23333【http©雙子宮殿】"; List<string> pattern = new List<string>();
先來個最簡單的開個味,太深了都沒有興趣往下看了
pattern.Add("http");//常量匹配 result = 2
沒有任何的正則表達式的元字元(也就是保留字),http在input裡面有2個,所以匹配到了2條
基礎篇
一、基本語義描述符
1、\d(數字字元)與\D(非數字字元)
pattern.Add("233\\d");//匹配233+數字字元 result=1 pattern.Add("233\\D");//匹配233+非數字字元 result=1
2、\w(字母數字下劃線)與\W(非字母數字下劃線)
pattern.Add("\\w");//匹配字母+數字+下劃線 result=36 pattern.Add("\\W");//不匹配字母+數字+下劃線 result=11
註意:實測\w是能匹配到中文的
3、\s(空白字元)與\S(非空白字元)
空白字元包括製表符、換行符、垂直製表符、換頁符、回車符

pattern.Add("\t");//匹配製表符 等價於\x09 pattern.Add("\n");//匹配換行符 等價於\x0A pattern.Add("\v");//匹配垂直製表符 等價於\x0B pattern.Add("\f");//匹配換頁符 等價於\x0C pattern.Add("\r");//匹配回車符 等價於\x0D pattern.Add("\\s");//匹配任何空白字元 等價於[\t\n\v\f\r] pattern.Add("\\S");//匹配任何非空白字元 等價於[\t\n\v\f\r]

到這裡就需要說明一下了,\和\\的區別
\是C#的轉義符,如果要讓C#把\當字元處理,要使用\\
或者在字元串前使用@告訴C#這個字元串的反斜杠都當字元處理
pattern.Add(@"\s");
註意:如果一個字元串裡面有多個\,有表示轉義符,也有表示字元的,那就不能在字元串之前用@,只能用\\來區分
4、.(任何字元,除\n)
pattern.Add(".");//匹配除 "\n" 之外的任何字元 result=49
5、\xXX(單位元組)與\uXXXX(雙位元組)
\xXX單位元組字元,字元對應轉義值可以查ASCII碼表
pattern.Add("\x61");//匹配單位元組字元(x61=a) result=2 pattern.Add("\x20");//匹配單位元組字元(x20=空格) result=1
\uXXXX雙位元組字元,除常用字元之外的所有字元,包括各種不常用字元和各國語言字元等等
pattern.Add("\u00A9");//匹配雙位元組(u00A9=©) result=1 pattern.Add("[\u4e00-\u9fa5]");//匹配雙位元組([\u4e00-\u9fa5]=漢字) result=8
二、定位描述符
1、^ (匹配字元串的開始位置)
pattern.Add("^http");//開始位置匹配 result = 1 pattern.Add("^tansea");//開始位置匹配 result = 0
input確實是以http開頭的,所以匹配到了1條,而下麵那條語句沒有匹配到記錄
2、$(匹配字元串的結束位置)
pattern.Add("】$");//結束位置匹配 result = 1
3、\b(空格)與\B(非空格)
pattern.Add("23\\b");//匹配23+空格 result=1 pattern.Add("23\\B");//匹配23+非空格 result=2
三、重覆描述符
1、*(匹配0-∞次 等價於{0,})
pattern.Add("233*");//以23開頭,後面接0到n個3匹配 result=3
匹配到23、233、23333三條記錄
2、+(匹配1-∞次 等價於{1,})
pattern.Add("233+");//以23開頭,後面接1到n個3匹配 result=2
匹配到233、23333兩條記錄
3、?(匹配0-1次 等價於{0,1})
pattern.Add("233?");//以23開頭,後面接0到1個3匹配 result=3
匹配到23、233、233(23333前面部分)三條記錄
4、{n}(匹配n次,n>0)
pattern.Add("233{1}");//以23開頭,後面接1個3匹配 result=2
匹配到233、233(23333前面部分)兩條記錄
5、{n,}(匹配n-∞次,n>0)
pattern.Add("233{1,}");//以23開頭,後面接1到無限個3匹配 result=2
匹配到233、23333兩條記錄
6、{n,m}(匹配n-m次,n>0 且 n<=m)
pattern.Add("233{2,3}");//以23開頭,後面接2到3個3匹配 result=1
匹配到23333一條記錄
四、選擇描述符
1、|(或操作)
pattern.Add("com|cn|net");//或條件 result=1
2、[](IN操作,匹配所包含的任意一個字元)
pattern.Add("[人從眾]");//IN條件 result=1
IN條件與或條件的區別:或條件是支持多字元,將一個段做為一個整體而IN條件只支持單字元
pattern.Add("[^人從眾]");//NOT IN條件 result=46 pattern.Add("[o-t]");//BETWEEN條件 匹配小寫o到小寫t result=8 pattern.Add("[^o-t]");//NOT BETWEEN條件 匹配非小寫o到小寫t result=39
五、組(...)與非捕獲組(?:...)
正則表達式會將刮號里的內容單獨保存成一個組,並且匹配到的組可以反向引用,\n是引用第n組
pattern.Add("\\.(.{1,6})");//.開頭取6個字元 result=2
結果:Group[0]=.tansea Group[1]=tansea
Group[0]=.cn/23 Group[1]=cn/23
註意:/23後面是有一個空格的,是取了6個字元
如果不想把刮號里的內容保存到組,可以用非捕獲組
pattern.Add("\\.(?:.{1,6})");
六、貪婪與非貪婪
正則表達式預設為貪婪模式,可以在重覆描述符後加上?改成非貪婪模式
pattern.Add(".*233");//結果為"http://www.tansea.cn/23 233【個人博客】233"一條記錄 pattern.Add(".*?233");//結果為"http://www.tansea.cn/23 233"、"【個人博客】233"兩條記錄
七、回溯與非回溯
正則表達式預設為回溯模式,可以(?>...)改成非回溯模式
在貪婪模式情況下,非回溯模式不會再重新去匹配,而是接著繼續匹配
pattern.Add("(.*)233");//結果為"http://www.tansea.cn/23 233【個人博客】233" pattern.Add("(?>.*)233");//結果為空
八、正向預搜索(?=...)與反向預搜索(?<=...)
1、正向預搜索
pattern.Add("\\d{3}(?=【個人博客】)");//匹配3個數字開頭後面是"【個人博客】" pattern.Add("\\d{3}(?!=【個人博客】)");//匹配3個數字開頭後面不是"【個人博客】"
2、反向預搜索
pattern.Add("(?<=【個人博客】)\\d{3}");//匹配"【個人博客】"開頭後面是3個數字 pattern.Add("(?!<=【個人博客】)\\d{3}");//匹配不是"【個人博客】"開頭後面是3個數字
可以看出來,當判斷條件在後面時,我們用的是正向預搜索,反之則相反。
預搜索刮號內的內容不會匹配
來看看結果吧

pattern.ForEach(p => { MatchCollection matches = Regex.Matches(input, p); Console.WriteLine("Count:" + matches.Count); foreach (Match item in matches) //Console.WriteLine("Value:" + item.Groups[0].Value); Console.WriteLine("Value:" + item.Groups[0].Value + "=>" + item.Groups[1].Value); });

實戰篇
一、Escape和Uescape

string input = @"\dhttp://www.tansea.cn2017"; string pattern = "\\d"; string replacement = "X"; string split = ":|/|\\."; //\d是元符號,將元符號轉換成原義解釋 string escapePattern = Regex.Escape(pattern); Console.WriteLine(Regex.Match(input, escapePattern).Groups[0].Value);//result=\d //\\d是原義,將原義轉換成元符號解釋 string unescapePattern = Regex.Unescape(escapePattern); Console.WriteLine(Regex.Match(input, unescapePattern).Groups[0].Value);//result=2

二、IsMatch
Regex.IsMatch(input, pattern);//是否找到匹配項
三、Match
Match match = Regex.Match(input, pattern);//返回匹配到的第一項 Console.WriteLine(match.Value);
四、Matches
MatchCollection matches = Regex.Matches(input, pattern);//返回匹配到的所有項 foreach (Match item in matches) Console.WriteLine(item.Value);
五、Replace

Console.WriteLine(Regex.Replace(input, pattern, replacement));//用指定的字元串替換匹配到的項 Console.WriteLine(Regex.Replace(input, pattern, m => { string result = string.Empty; switch (m.Value) { case "2": result = "貳"; break; case "0": result = "零"; break; case "1": result = "壹"; break; case "7": result = "柒"; break; } return result; }));//用委托返回的字元串替換匹配到的項

六、Split
List<string> inputs = Regex.Split(input, split).ToList();//以匹配到的項的位置為基本,拆分字元串 inputs.ForEach(i => Console.WriteLine(i));