最近寫爬蟲時須要用到正則表達式,有段時間沒有使用正則表達式如今漸漸感受有些淡忘,如今使用還須要去查詢一些資料。爲了不之後這樣的狀況,在此記錄下正則表達式的一些基本使用方法附帶小的實例。讓之後在使用時能一目瞭然知道他的使用,爲開發節約時間,同時也分享給你們。javascript
在說正則表達式以前咱們先來看看通配符,我想通配符你們都用過。通配符主要有星號(*)和問號(?),用來模糊搜索文件。winodws中咱們常會使用搜索來查找一些文件。如:*.jpg,XXX.docx的方式,來快速查找文件。其實正則表達式和咱們通配符很類似也是經過特定的字符匹配咱們所要查詢的內容信息。已下代碼都是區分大小寫。html
經常使用元字符java
代碼 | 說明 |
. | 匹配除換行符之外的任意字符。 |
\w | 匹配字母或數字或下劃線或漢字。 |
\s | 匹配任意的空白符。 |
\d | 匹配數字。 |
\b | 匹配單詞的開始或結束。 |
[ck] | 匹配包含括號內元素的字符 |
^ | 匹配行的開始。 |
$ | 匹配行的結束。 |
\ | 對下一個字符轉義。好比$是個特殊的字符。要匹配$的話就得用\$ |
| | 分支條件,如:x|y匹配 x 或 y。 |
反義元字符正則表達式
代碼 | 說明 |
\W | 匹配任意不是字母,數字,下劃線,漢字的字符。 |
\S | 匹配任意不是空白符的字符。等價於 [^ \f\n\r\t\v]。 |
\D | 匹配任意非數字的字符。等價於 [^0-9]。 |
\B | 匹配不是單詞開頭或結束的位置。 |
[^CK] | 匹配除了CK之外的任意字符。 |
特殊元字符ide
代碼 | 說明 |
\f | 匹配一個換頁符。等價於 \x0c 和 \cL。 |
\n | 匹配一個換行符。等價於 \x0a 和 \cJ。 |
\r | 匹配一個回車符。等價於 \x0d 和 \cM。 |
\t | 匹配一個製表符。等價於 \x09 和 \cI。 |
\v | 匹配一個垂直製表符。等價於 \x0b 和 \cK。 |
限定符函數
代碼 | 說明 |
* | 匹配前面的子表達式零次或屢次。 |
+ | 匹配前面的子表達式一次或屢次。 |
? | 匹配前面的子表達式零次或一次。 |
{n} | n 是一個非負整數。匹配肯定的 n 次。 |
{n,} | n 是一個非負整數。至少匹配n 次。 |
{n,m} | m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。 |
懶惰限定符this
代碼 | 說明 |
*? | 重複任意次,但儘量少重複。google 如 "acbacb" 正則 "a.*?b" 只會取到第一個"acb" 本來能夠所有取到但加了限定符後,只會匹配儘量少的字符 ,而"acbacb"最少字符的結果就是"acb" 。spa |
+? | 重複1次或更屢次,但儘量少重複。與上面同樣,只是至少要重複1次。 |
?? | 重複0次或1次,但儘量少重複。.net 如 "aaacb" 正則 "a.??b" 只會取到最後的三個字符"acb"。 |
{n,m}? | 重複n到m次,但儘量少重複。 如 "aaaaaaaa" 正則 "a{0,m}" 由於最少是0次因此取到結果爲空。 |
{n,}? | 重複n次以上,但儘量少重複。 如 "aaaaaaa" 正則 "a{1,}" 最少是1次因此取到結果爲 "a"。 |
捕獲分組
代碼 | 說明 |
(exp) | 匹配exp,並捕獲文本到自動命名的組裏。 |
(?<name>exp) | 匹配exp,並捕獲文本到名稱爲name的組裏。 |
(?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號如下爲零寬斷言。 |
(?=exp) | 匹配exp前面的位置。 如 "How are you doing" 正則"(?<txt>.+(?=ing))" 這裏取ing前全部的字符,並定義了一個捕獲分組名字爲 "txt" 而"txt"這個組裏的值爲"How are you do"; |
(?<=exp) | 匹配exp後面的位置。 如 "How are you doing" 正則"(?<txt>(?<=How).+)" 這裏取"How"以後全部的字符,並定義了一個捕獲分組名字爲 "txt" 而"txt"這個組裏的值爲" are you doing"; |
(?!exp) | 匹配後面跟的不是exp的位置。 如 "123abc" 正則 "\d{3}(?!\d)"匹配3位數字後非數字的結果 |
(?<!exp) | 匹配前面不是exp的位置。 如 "abc123 " 正則 "(?<![0-9])123" 匹配"123"前面是非數字的結果也可寫成"(?!<\d)123" |
獲得上面祕籍後咱們能夠小試牛刀...
在C#中使用正則表達式主要是經過Regex類來實現。命名空間:using System.Text.RegularExpressions。
其中經常使用方法:
名稱 | 說明 |
IsMatch(String, String) | 指示 Regex 構造函數中指定的正則表達式在指定的輸入字符串中是否找到了匹配項。 |
Match(String, String) | 在指定的輸入字符串中搜索 Regex 構造函數中指定的正則表達式的第一個匹配項。 |
Matches(String, String) | 在指定的輸入字符串中搜索正則表達式的全部匹配項。 |
Replace(String, String) | 在指定的輸入字符串內,使用指定的替換字符串替換與某個正則表達式模式匹配的全部字符串。 |
Split(String, String) | 在由 Regex 構造函數指定的正則表達式模式所定義的位置,拆分指定的輸入字符串。 |
在使用正則表達式前咱們先來看看「@」符號的使用。
學過C#的人都知道C# 中字符串常量能夠以@ 開頭聲名,這樣的優勢是轉義序列「不」被處理,按「原樣」輸出,即咱們不須要對轉義字符加上 \ (反斜扛),就能夠輕鬆coding。如:
string filePath = @"c:\Docs\Source\CK.txt" // rather than "c:\\Docs\\Source\\CK.txt"
如要在一個用 @ 引發來的字符串中包括一個雙引號,就須要使用兩對雙引號了。這時候你不能使用 \ 來轉義爽引號了,由於在這裏 \ 的轉義用途已經被 @ 「屏蔽」掉了。如:
string str=@"""Ahoy!"" cried the captain." // 輸出爲: "Ahoy!" cried the captain.
字符串匹配:
在實際項目中咱們經常須要對用戶輸入的信息進行驗證。如:匹配用戶輸入的內容是否爲數字,是否爲有效的手機號碼,郵箱是否合法....等。
實例代碼:
string RegexStr = string.Empty; #region 字符串匹配 RegexStr = "^[0-9]+$"; //匹配字符串的開始和結束是否爲0-9的數字[定位字符] Console.WriteLine("判斷'R1123'是否爲數字:{0}", Regex.IsMatch("R1123", RegexStr)); Console.WriteLine("判斷'1123'是否爲數字:{0}", Regex.IsMatch("1123", RegexStr)); RegexStr = @"\d+"; //匹配字符串中間是否包含數字(這裏沒有從開始進行匹配噢,任意位子只要有一個數字便可) Console.WriteLine("'R1123'是否包含數字:{0}", Regex.IsMatch("R1123", RegexStr)); Console.WriteLine("'博客園'是否包含數字:{0}", Regex.IsMatch("博客園", RegexStr)); 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:指定不區分大小寫的匹配。 #endregion
顯示結果:
字符串查找:
實例代碼:
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匹配包含括號內元素的字符 Console.WriteLine("{0}。GetH1值:{1}", "<H1>標題<H1>", Regex.Match("<H1>標題<H1>", RegexStr, RegexOptions.IgnoreCase).Value); Console.WriteLine("{0}。GetH1值:{1}", "<h2>小標<h2>", Regex.Match("<h2>小標<h2>", RegexStr, RegexOptions.IgnoreCase).Value); //RegexOptions.IgnoreCase:指定不區分大小寫的匹配。 RegexStr = @"ab\w+|ij\w{1,}"; //匹配ab和字母 或 ij和字母 Console.WriteLine("{0}。多選結構:{1}", "abcd", Regex.Match("abcd", RegexStr).Value); Console.WriteLine("{0}。多選結構:{1}", "efgh", Regex.Match("efgh", RegexStr).Value); Console.WriteLine("{0}。多選結構:{1}", "ijk", Regex.Match("ijk", RegexStr).Value); RegexStr = @"張三?豐"; //?匹配前面的子表達式零次或一次。 Console.WriteLine("{0}。可選項元素:{1}", "張三丰", Regex.Match("張三丰", RegexStr).Value); Console.WriteLine("{0}。可選項元素:{1}", "張豐", Regex.Match("張豐", RegexStr).Value); Console.WriteLine("{0}。可選項元素:{1}", "張飛", Regex.Match("張飛", RegexStr).Value); /* 例如: July|Jul 可縮短爲 July? 4th|4 可縮短爲 4(th)? */ //匹配特殊字符 RegexStr = @"Asp\.net"; //匹配Asp.net字符,由於.是元字符他會匹配除換行符之外的任意字符。這裏咱們只須要他匹配.字符便可。因此須要轉義\.這樣表示匹配.字符 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
顯示結果:
貪婪與懶惰
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}懶惰匹配(匹配儘量少重複):{1}", f, m2.ToString());
顯示結果:
從上面的例子中咱們不難看出貪婪與懶惰的區別,他們的名子取的都很形象。
貪婪匹配:匹配儘量多的字符。
懶惰匹配:匹配儘量少的字符。
(exp)分組
在作爬蟲時咱們常常得到A中一些有用信息。如href,title和顯示內容等。
string TaobaoLink = "<a href=\"http://www.taobao.com\" title=\"淘寶網 - 淘!我喜歡\" 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); }
顯示結果:
在正則表達式裏使用()包含的文本自動會命名爲一個組。上面的表達式中共使用了4個()能夠認爲是分爲了4組。
輸出結果共分爲:4組。
0組:爲咱們所匹配的字符串。
1組:是咱們第一個括號[href=""(\S+)""]中(\S+)所匹配的網址信息。內容爲:http://www.taobao.com。
2組:是第二個括號[title=""([\s\S]+?)""]中所匹配的內容信息。內容爲:淘寶網 - 淘!我喜歡。
這裏咱們會看到+?懶惰限定符。title=""([\s\S]+?)"" 這裏+?的下一個字符爲"雙引號,"雙引號在匹配字符串後面還有三個。+?懶惰限定符會盡量少重複,所他會匹配最前面那個"雙引號。若是咱們不使用+?懶惰限定符他會匹配到:淘寶網 - 淘!我喜歡" target= 會盡量多重複匹配。
3組:是第三個括號[(\S+)]所匹配的內容信息。內容爲:淘寶。
說明:反義元字符所對應的元字符都能組合匹配任意字符。如:[\w\W],[\s\S],[\d\D]..
(?<name>exp) 分組取名
當咱們匹配分組信息過多後,在某種場合只需取當中某幾組信息。這時咱們能夠對分組取名。經過分組名稱來快速提取對應信息。
string Resume = "基本信息姓名:CK|求職意向:.NET軟件工程師|性別:男|學歷:本專|出生日期:1988-08-08|戶籍:湖北.孝感|E - Mail:9245162@qq.com|手機:15000000000"; RegexStr = @"姓名:(?<name>[\S]+)\|\S+性別:(?<sex>[\S]{1})\|學歷:(?<xueli>[\S]{1,10})\|出生日期:(?<Birth>[\S]{10})\|[\s\S]+手機:(?<phone>[\d]{11})"; Match matc = Regex.Match(Resume, RegexStr); Console.WriteLine("姓名:{0},手機號:{1}", matc.Groups["name"].ToString(), matc.Groups["phone"].ToString());
顯示結果:
經過(?<name>exp)能夠很輕易爲分組取名。而後經過Groups["name"]取得分組值。
得到頁面中A標籤中href值
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()); }
顯示結果:
Replace 替換字符串
用戶在輸入信息時偶爾會包含一些敏感詞,這時咱們須要替換這個敏感詞。
string PageInputStr = "靠.TMMD,今天真不爽...."; RegexStr = @"靠|TMMD|媽的"; Regex rep_regex = new Regex(RegexStr); Console.WriteLine("用戶輸入信息:{0}", PageInputStr); Console.WriteLine("頁面顯示信息:{0}", rep_regex.Replace(PageInputStr, "***"));
顯示結果:
對一些敏感詞直接替換成***代替。
Split 拆分字符串
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); }
顯示結果:
根據數字截取字符串。
轉自 http://www.cnblogs.com/caokai520/p/4511848.html