今日隨筆,繼續寫一些關於正則表達式的東西。
首先補一點昨天的內容:
昨天少說了一個貪婪模式,什么是貪婪模式,比如像+或者*這樣的元字符匹配中,會以最大匹配值匹配,這句話是什么意思呢,例如:
定義一個正則表達式模式:ab+ ,然后又這樣一個字符串"csddabbbbbbbbbbbbaaaa" 那么他匹配出來的字符串就是abbbbbbbbbbbb,而不是ab或者abbbb等等。都是匹配的符合的最大的字符串長度。
那什么時候終結貪婪模式呢? 就是在+或者*這樣的元字符后面加一個“?”,還拿上面的例子說明 如果定義的正則表達式模式:“ab+?”,那么字符串"csddabbbbbbbbbbbbaaaa"與其匹配的結果就是ab,這樣就看出終結貪婪模式的意思了吧,正酣和貪婪模式相反,是匹配的符合的最小的字符串長度。
好了,上一節主要介紹了Regex類的IsMatch方法,其方法主要是判斷字符串是否與正則表達式匹配,主要是在一些驗證中用到,比如在網頁注冊中驗證輸入的郵箱地址啊,生分證號是否正確等等(這里要說一下,正則表達式是不分語言的,不如^、$、[]等這些元字符在c++中java或者js語言中都是這么用的)。
那么,現在老板有這樣一個需求,給你一些網頁,讓你收集這些網頁上的所有emai地址,然后記錄下來查到數據庫中,方便以后給這些郵箱發送我電商網站的促銷信息。
怎么辦? 去這些網頁里面一個一個找到email?然后一個一個的查到數據庫?,我勒個去,太恐怖了吧。
但是,如果你懂得正則表達式的匹配,你就會發現,Is so easy。。。
啥都不說,先上一個例子,比如我要收集這樣的一個網頁中的email:
//------第一個要求,查找一個網頁上的所有email地址,並且提取出來 string str = File.ReadAllText("大家留下email交友吧_email_天涯社區.htm"); //string regex = @"\w+@\w+(\.\w+){1,3}"; string regex = @"[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+){1,3}";//這個就不用我解釋了吧,看過上一章的小伙伴們應該都明吧 MatchCollection coll = Regex.Matches(str, regex); foreach (Match item in coll) { Console.WriteLine(item.Value); }
顯示結果:
現在讓我們來解釋一下代碼吧,首先用一個string變量str接受要收集網頁的所有內容,然后又定義了email的正則表達式模式regex,這里要注意一下,這個模式和上個模式中少了^$,這里為什么不加這兩個元字符了呢,其實想想也知道,我只要在網頁中找到其中可以匹配的regex就可以了,而不是讓整個str字符串與regex。
然后我們調用了Regex類的Matchs方法,這個方法表示 在指定的輸入字符串中搜索指定的正則表達式的所有匹配項,返回結果:搜索操作找到的System.Text.RegularExpressions.Match隊形的集合,類型是MatchCollection,然后循環這個集合,調用Match的value屬性就能得到匹配的email地址。
恩。。。 ,還有一些其他屬性和方法小伙伴們可以自己去看一下,很簡單的 相信大家一看就能明吧。
是不是感覺很簡單,哈,那么,現在老板又有要求了,他說把提取出的每個email做個對比,看看哪域名的email用的最多。
額。。。email的域名是什么? 就是像@gmail.com這樣的東東啦。
該怎么做呢,用字符串截取?當然可以,而且也很好實現,但是要是也是用正則表達式的知識呢?
解決這個問題之前,讓我們再來了解一正則表達式中“提取組”這個么個東西,什么是提取組,其實就是在正則表達式模式中加入“()”個東西包起來就是一個提取組,例如:
定義一個表達式模式regex = "name=(\w+)age=(\d{0,2})",我們可以看出在名字的地方有了“()”給包了起來,這就是一個組,在年齡的地方又用"()"包了起來,這又是一個組。,那說了這么多,這個組到時是干啥用的呢,
那么我現在有着樣一個字符串與其匹配:str ="name=小強age=23":代碼如下:
string regex = @"name=(\w+)age=(\d{0,2})"; string str = "name=小強age=23"; Match match = Regex.Match(str, regex); Console.WriteLine("name:{0},age:{1}", match.Groups[1].Value, match.Groups[2].Value); //輸出結果 name:小強,age:23
Match類中有一個Groups屬性,它就是一個組的集合,他的索引是從0開始的,但是索引是0的值是匹配regex模式的在字符串的本身,在這里match.Groups[0].Value得值就是"name=小強age=23",在regex模式中,有兩個組,一個是(\w+),一個是(\d{0.3}),怎么判斷它的順序呢,哪個是第一組,哪個是第二種,現這種的還很好判斷從左到又唄,但是像(a((b)c(d))ef(g))這樣的,怎么判斷呢,其實很簡單,從左到右看“(”第幾個出現就是第幾組。
這樣,我們就可以在匹配完成后的字符串中繼續按着自己的意願分組得到相應的結果(這里我得到的是名字和年齡)。
好了,現在讓我們回到老板的第二個需求,那么我只需要在正則表達式模式中給域名的那一本分用"()"包起來,分成一個組,然后遍歷的時候給它放到字典中作為key值,其value值設為0,如果下次再出現的時候,我就讓他的value加一上1
代碼:
//------第二個要求 我希望把提取出的每個email做個對比,看看哪域名的email用的最多 string str = File.ReadAllText("大家留下email交友吧_email_天涯社區.htm"); string regex = @"[a-zA-Z0-9_]+@([a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+){1,3})"; MatchCollection coll = Regex.Matches(str, regex); Dictionary<string, int> dic = new Dictionary<string, int>(); foreach (Match item in coll) { if (!dic.ContainsKey(item.Groups[1].ToString().ToLower())) { dic.Add(item.Groups[1].ToString().ToLower(), 1); } else { dic[item.Groups[1].ToString().ToLower()]++; } } //遍歷字典 foreach (var item in dic) { Console.WriteLine("域名:" + item.Key + " 使用的個數:" + item.Value); } //---------------end----------------------
輸出結果:
然后再和大家分享幾個例子:
#region "192.168.10.5[port=21,type=ftp]",這個字符串表示ip地址是192.168.10.5的服務器的21號端口提供ftp服務,其中若果ftp被省略,則默認是http服務,請解析此字符串然后打印出“IP地址是。。。端口是。。。提供的服務是。。。” string regex = @"^((\d{1,3}\.){3}\d{1,3})\[port=(\d{2,6})(,type=(\w+))?\]$"; while (true) { string ipCode = Console.ReadLine(); Match match = Regex.Match(ipCode, regex); if (match.Success)//這里也是判斷是否匹配成功 { string ip = match.Groups[1].Value; string port = match.Groups[3].Value; string serverType = "http"; if (match.Groups[5].Success) serverType = match.Groups[5].Value; //string serverType = string.IsNullOrEmpty(match.Groups[5].Value) ? "http" : match.Groups[5].Value; Console.WriteLine("IP地址是{0},端口是{1},提供的服務是{2}", ip, port, serverType); } else { Console.WriteLine("輸入的不是正確的ip地址"); } } #endregion
#region 字符串替換 將aaaaaaabbbbbbbbbccccccccc 變成abc string str = "aaaaaaabbbbbbbbbccccccccc"; Console.WriteLine(Regex.Replace(str, @"aa|bb|cc", "")); #endregion
好啦 今天就寫到這吧,然后呢還是希望大家能給出各種建議,不對的地方請指出,我會非常感謝的並且虛心改正,如果今天和昨天的那些例子住有的小伙伴不明白的,也請留言具體指出哪個還不太理解,我也會盡力給予解答,最后希望我的隨筆可以給大家帶來一些收獲。 晚安,小伙伴們。