正則表達式很強大且內(nèi)容比較多。不少初學者學這個表示很困難。故寫一篇入門的教程。
1、什么是正則表達式正則表達式是一個天才創(chuàng)建的用于快速檢索匹配字符串,通過簡單的表達式匹配文本。
2、正則表達式的組成正則表達式也是一個字符串,包括元字符、限定符和正常意義的字符。正則表達式強大的地方就在元字符和限定符。
3、限定符很多人講這個都是先講元字符。其實先講限定符更加容易吸收。限定符是表示前面字符或元字符出現(xiàn)的次數(shù)。主要限定符如下: 限定符 | 含義 | * | 表示前面字符或元字符出現(xiàn)0次或多次。例如:zo*m,可以匹配zm,zom,zoom | + | 表示前面字符或元字符出現(xiàn)1次或多次。例如:zo+m,可以匹配zom,zoom | ? | 表示前面字符或元字符出現(xiàn)0次或1次。例如:zo?m,可以匹配zm,zom | {n} | 表示前面字符或元字符出現(xiàn)n次。例如:zo{3}m,可以匹配zooom | {n,m} | 表示前面字符或元字符出現(xiàn)n到m次。例如:zo{1,3}m,可以匹配zom,zoom,zooom | {n,} | 表示前面字符或元字符至少出現(xiàn)n次。例如:zo{2,}m,可以匹配zoom,zooom等等 |
當然,限定符用法不止這些。正則表達式還有個規(guī)則叫貪婪與吝嗇。有些人也叫貪婪與懶惰。這個“貪婪與吝嗇”是正則表達式難點和重點之一。 例如,字符串“n123n456n789n”。那么我們怎么匹配獲取“n123n”和“n123n456n789n”呢。 使用正則表達式,首先要找規(guī)律。很明顯我們要獲取的內(nèi)容開頭和結(jié)尾都有一個字母n,中間是數(shù)字或字母。我們先學一個元字符。元字符是可以代表一定含義或規(guī)律的字符。可以匹配除了換行符之外的任意字符是小數(shù)點。 那么我們的表達式可以這么寫:n.+n 兩個字母n,中間夾著1個或多個任意字符。 但這樣只能匹配得到一個結(jié)果:n123n456n789n。在我們沒有對其任何限制的情況下,正則表達式會盡可能多匹配符合條件的結(jié)果。從頭到尾整個都符合,所以都匹配了。這個稱之為貪婪匹配。 那如何做到盡可能少的匹配。這個就需要加個?進行限制。 例如,表達式:n.+?n 這個表達式盡可能少匹配,也就是說碰到一次符合條件的就立馬返回結(jié)果。結(jié)果可以匹配到“n123n”、“n789n”。 這種規(guī)則叫做吝嗇匹配。只要在限定符后面再加個問號即可。
4、元字符元字符是用于匹配字符串,可以代表一定含義或規(guī)律的字符串。主要的元字符如下: 元字符 | 含義 | . | 小數(shù)點,代表除了換行符以外的任意字符 | \ | 轉(zhuǎn)義,若我想匹配一些被正則表達式占用的字符,例如小數(shù)點,可以用\. | [abc] | 匹配中括號內(nèi)的字符,例如[a-zA-Z],可以匹配到大小寫字母 | [^abc] | 不匹配中括號內(nèi)的字符,例如[^a-z],表示不匹配小寫字母 | \w | 可以匹配字母、下劃線和數(shù)字,相當于[a-zA-Z0-9_] | \W | 大寫的W是小寫的w相反情況,也就是不匹配字母、下劃線和數(shù)字。相當于[^a-zA-Z0-9_] | \s | 匹配任意空白符,相當于[\f\n\r\t\v] | \S | 匹配任意非空符,相當于[^\f\n\r\t\v]或[^\s] | \d | 匹配數(shù)字,相當于[0-9] | \D | 匹配非數(shù)字,相當于[^0-9] | \b | 匹配單詞的邊界。這個匹配英文單詞特別有用。例如\b[\w']+?\b就可以匹配任意單詞了 | \f | 匹配換頁符 | \n | 匹配換行符 | \r | 匹配回車符 | \t | 匹配tab制表符 | \v | 匹配垂直制表符 | ^ | 不在中括號內(nèi)的^,表示從字符串的開頭開始匹配 | $ | 表示匹配到字符串的結(jié)尾 | x|y | 匹配x或y | (表達式) | 元組,用小括號括起來的表達式當作一個元組,可以當作一個整體,也可以被\1\2\3這樣類似索引獲取。 |
元字符比較多,這里就建議大家先收藏,需要用的時候再查閱。多用幾次就自然記住了。 這里還有個小技巧,若我想匹配全部任意字符,包括換行符??梢杂靡唤M相反的元字符,例如[\s\S],就可以匹配全部任意字符。
5、常見的正則表達式 說了這么多,暈了沒?看一些實例: 1)匹配郵編,郵編是6位數(shù)字。正則表達式:\d{6} 2)匹配手機,手機號是11位數(shù)字。正則表達式:\d{11} 3)匹配電話,電話是區(qū)號-號碼組成,區(qū)號有3到4位,號碼有6到9位。正則表達式:\d{3,4}-\d{6,9} 4)匹配日期,日期格式如1992-5-30,明顯數(shù)字加橫線組成。正則表達式:\d{4}-\d{1,2}-\d{1,2} 5)匹配漢字,漢字需要通過編碼轉(zhuǎn)義,漢字都unicode編碼中都在一個范圍內(nèi)。正則表達式:[\u4e00-\u9fa5]
6、vba中使用正則表達式 若只是上面這些內(nèi)容,那么還是紙上談兵,需要應(yīng)用到實際中??纯慈绾卧趘ba中使用正則表達式。 vba使用正則表達式需要用到一個RegExp對象。 該對象可以通過引用Microsoft VBScript Regular Expressions 5.5。再聲明定義: - Dim reg As New RegExp
還可以直接用CreateObject方法創(chuàng)建: - Dim reg As Object
- set reg = CreateObject("VBScript.Regexp")
創(chuàng)建RegExp對象之后,看看它的相關(guān)屬性和方法。 屬性: 1)Global,是否全局匹配,若為False,匹配到一個結(jié)果之后,就不再匹配。默認False,建議設(shè)為True; 2)IgnoreCase,是否忽略大小寫,默認False,建議設(shè)為False,這個會影響到正常表達式匹配; 3)Multiline,是否跨行匹配,默認False,建議設(shè)為False,這個會影響到正常表達式匹配; 4)Pattern,獲取或設(shè)置正則表達式。
方法: 1)Execute,執(zhí)行匹配 2)Replace,根據(jù)正確表達式全部替換 3)Test,測試正則表達式能否匹配到內(nèi)容
舉一些典型的例子: 1)判斷是否存在數(shù)字 - Public Function CheckNumber(str As String) As Boolean
- Dim reg As Object
- Set reg = CreateObject("VBScript.Regexp")
-
- Dim is_exist As Boolean
- With reg
- .Global = True
- .Pattern = "\d"
- is_exist = .Test(str)
- End With
- CheckNumber = is_exist
- End Function
用Test方法,判斷能否匹配到數(shù)字。
2)獲取所有編號 - Public Sub GetCode()
- Dim reg As Object
- Set reg = CreateObject("VBScript.Regexp")
-
- Dim str As String
- str = "編號:ABC123155 日期:2016-01-11" & _
- "編號:ABD134215 日期:2016-02-21" & _
- "編號:CBC134216 日期:2016-01-15"
-
- reg.Global = True reg.Pattern = "[A-Z]{3}\d+" '獲取匹配結(jié)果'
- Dim matches As Object, match As Object
- Set matches = reg.Execute(str)
-
- '遍歷所有匹配到的結(jié)果'
- For Each match In matches
- '測試輸出到立即窗口'
- Debug.Print match
- Next
- End Sub
因為這個編號是3個大寫字母和多個數(shù)字組成??梢岳么a中的表達式匹配到3個結(jié)果:ABC123155、ABD134215和CBC134216。
3)去掉字符串中的數(shù)字 - Public Function ClearNumber(str As String) As String
- Dim reg As Object
- Set reg = CreateObject("VBScript.Regexp")
-
- reg.Global = True
- reg.Pattern = "\d"
-
- '把所有數(shù)字替換成空'
- ClearNumber = reg.Replace(str, "")
- End Function
執(zhí)行ClearNumber函數(shù),即可去掉數(shù)字。例如ClearNumber("你342好234啊"),可得到"你好啊"。
4)獲取子字符串 例如想獲取某些字符串中的部分數(shù)據(jù),可以匹配完成之后,再用字符串函數(shù)處理。但其實不用,用元組可以一次性搞定。 - Public Sub GetHref()
- Dim reg As Object
- Set reg = CreateObject("VBScript.Regexp")
-
- Dim str As String
- str = "<a href='xxx1'>xxx1</a><a href='xxx2'>xxx2</a>"
-
- reg.Global = True
- '獲取a標簽中href的屬性值'
- reg.Pattern = "href='(.+?)'"
-
- '獲取匹配結(jié)果'
- Dim matches As Object, match As Object
- Set matches = reg.Execute(str)
-
- '遍歷所有匹配到的結(jié)果'
- For Each match In matches
- '測試輸出子表達式到立即窗口'
- Debug.Print match.SubMatches(0)
- Next
- End Sub
這里,可以通過match的SubMatches集合獲取元組里面的內(nèi)容。輕松得到xxx1和xxx2。
7、其他說明 vba的正則表達式不是很完整,沒有遞歸的功能。遞歸是可以匹配公式或html代碼等。有興趣可以了解一下。
(原創(chuàng)博文,轉(zhuǎn)載請注明來自 楊仕航的博客!本文鏈接:http:///blog/94)
如何在Excel VBA 中使用正則表達式? https://jingyan.baidu.com/article/046a7b3efcc75af9c37fa944.html 在“代碼窗口“中復(fù)制粘貼以下代碼: Sub RegTest() '定義正則表達式對象 Dim oRegExp As Object '定義匹配字符串集合對象 Dim oMatches As Object '創(chuàng)建正則表達式 '定義要執(zhí)行正則查找的文本變量 Dim sText As String sText = "這是v一個正則表達式b的范例程序a代碼" Set oRegExp = CreateObject("vbscript.regexp") With oRegExp '設(shè)置是否匹配所有的符合項,True表示匹配所有, False表示僅匹配第一個符合項 .Global = True '設(shè)置是否區(qū)分大小寫,True表示不區(qū)分大小寫, False表示區(qū)分大小寫 .IgnoreCase = True '設(shè)置要查找的字符模式 .Pattern = "[\u4e00-\u9fa5]+" '判斷是否可以找到匹配的字符,若可以則返回True MsgBox .Test(sText) '對字符串執(zhí)行正則查找,返回所有的查找值的集合,若未找到,則為空 Set oMatches = .Execute(sText) '把字符串中用正則找到的所有匹配字符替換為其它字符 MsgBox .Replace(sText, "") End With Set oRegExp = Nothing Set oMatches = Nothing End Sub
執(zhí)行以上代碼,將把 sText = "這是v一個正則表達式b的范例程序a代碼" 變量中的中文字符全部刪除,將只返回"vba"3個英文字符,如下圖所示。其中的.Pattern = "[\u4e00-\u9fa5]+"表示匹配所有中文字符,Pattern屬性是正則表達式對象的核心,當需要執(zhí)行其它查找替換時一般都只需更改Pattern屬性即可。 一些常見的正則Pattern如下: [0-9]表示匹配任意一個數(shù)字 [a-zA-Z]表示匹配任意一個英文字母 [\u4e00-\u9fa5]表示匹配任意一個中文字符
Excel vba 網(wǎng)抓天氣預(yù)報 最近在弄Excel vba 網(wǎng)抓教程,寫了不少實例。春節(jié)過后,寫個網(wǎng)抓天氣預(yù)報。
這個天氣預(yù)報有現(xiàn)成的接口,不過要注冊賬號什么的,有些麻煩。所以,我打算直接抓取“中國天氣網(wǎng)”的數(shù)據(jù)。
在第一個表格加一個按鈕,選擇省份和城市,再點擊按鈕即可。那些城市代碼信息也是我自己收集整理的,弄了一個下拉框聯(lián)動。效果如下圖: 
代碼如下: - '按鈕點擊事件'
- Sub btnQuery_Click()
- On Error GoTo Err_Handle:
- Dim strCity As String
- strCity = WorksheetFunction.VLookup([B2], [城市代碼表!A:B], 2, 0)
- GetWeather strCity
- Exit Sub
- Err_Handle:
- MsgBox "請選擇省份和城市"
- End Sub
-
- '網(wǎng)抓數(shù)據(jù)'
- '參數(shù):strCity 字符串,城市代碼'
- Public Sub GetWeather(strCity As String)
- On Error GoTo Err_Handle:
- [A5:D11].ClearContents '清空數(shù)據(jù)'
-
- '創(chuàng)建XmlHttp對象'
- Dim xmlHttp As Object
- Set xmlHttp = CreateObject("MSXML2.XMLHTTP")
-
- '創(chuàng)建并發(fā)送請求'
- xmlHttp.Open "GET", "http://www.weather.com.cn/weather/" & strCity & ".shtml", False
- xmlHttp.setRequestHeader "If-Modified-Since", "0" '不要緩存'
- xmlHttp.Send
-
- '等待響應(yīng)'
- Do While xmlHttp.readyState <> 4
- DoEvents
- Loop
-
- '得到響應(yīng)結(jié)果'
- Dim strResponse As String
- strResponse = xmlHttp.responsetext
-
- '創(chuàng)建正則表達式對象'
- Dim regExp As Object
- Set regExp = CreateObject("VBScript.RegExp")
-
- '設(shè)置正則表達式'
- regExp.Global = True
-
- '這個表達式比較復(fù)雜,估計只有上帝和我知道是怎么回事。'
- '過段時間應(yīng)該就只有上帝才知道。'
- '具體分析可以看我的《Excel vba 網(wǎng)抓教程》'
- regExp.Pattern = "([\s\S]+?)[\s\S]+?""wea"">([\s\S]+?)[\s\S]+?(\d+?)[\s\S]+?([\s\S]+?)[\s\S]+?([\s\S]+?)"
-
- '匹配結(jié)果'
- Dim matches As Object, i As Long, arr()
- Set matches = regExp.Execute(strResponse)
- If matches.Count = 0 Then
- MsgBox "找不到天氣信息"
- Exit Sub
- End If
-
- '處理匹配結(jié)果'
- ReDim arr(matches.Count - 1, 3)
- For i = 0 To matches.Count - 1
- arr(i, 0) = matches(i).SubMatches(0)
- arr(i, 1) = matches(i).SubMatches(1)
- arr(i, 2) = matches(i).SubMatches(2) & "/" & matches(i).SubMatches(3)
- arr(i, 3) = matches(i).SubMatches(4)
- Next
-
- [A5:D11] = arr '寫到Excel中'
- Exit Sub
- Err_Handle:
- MsgBox Err.Description
- End Sub
原理不復(fù)雜,就是通過城市代碼抓取對應(yīng)的天氣預(yù)報數(shù)據(jù)。通過正則表達式匹配結(jié)果并處理。 百度網(wǎng)盤下載:http://pan.baidu.com/s/1eRdmpaU 密碼: ehq9 上一篇:Django在WebFaction服務(wù)器的郵箱設(shè)置 下一篇:Python字符串處理方法總結(jié)
|