正則表達(dá)式應(yīng)用技巧四則
來(lái)源:易賢網(wǎng) 閱讀:698 次 日期:2014-09-05 11:51:13
溫馨提示:易賢網(wǎng)小編為您整理了“正則表達(dá)式應(yīng)用技巧四則”,方便廣大網(wǎng)友查閱!

以前就想總結(jié)一下,一直沒(méi)有時(shí)間,今天看見(jiàn)了一篇好文,特此貢獻(xiàn)出來(lái),盡情享受正則的強(qiáng)大功能吧!!

以下為正文內(nèi)容:

------------------------------------------------------------

正則表達(dá)式(Regular Expression)為字符串模式匹配提供了一種高效、方便的方法。幾乎所有高級(jí)語(yǔ)言都提供了對(duì)正則表達(dá)式的支持,或者提供了現(xiàn)成的代碼庫(kù)供調(diào)用。本文以ASP環(huán)境中常見(jiàn)的處理任務(wù)為例,介紹正則表達(dá)式的應(yīng)用技巧。

一、檢驗(yàn)密碼和郵件地址的格式

我們的第一個(gè)實(shí)例示范正則表達(dá)式的一項(xiàng)基本功能:抽象地描述任意復(fù)雜的字符串。它的意思就是,正則表達(dá)式給予程序員一種形式化的字符串描述方法,只需很少的代碼即可描述出應(yīng)用遇到的任意字符串模式。例如,對(duì)于不從事技術(shù)工作的人來(lái)說(shuō),密碼格式的要求可以描述如下:密碼的第一個(gè)字符必須是字母,密碼最少4個(gè)字符且不超過(guò)15個(gè)字符,密碼不能包含除字母、數(shù)字和下劃線以外的字符。

作為程序員,我們必須把上面對(duì)密碼格式的自然語(yǔ)言描述轉(zhuǎn)換成其他形式,使得ASP頁(yè)面能夠理解并應(yīng)用它來(lái)防止非法的密碼輸入。描述這個(gè)密碼格式的正則表達(dá)式是:^[a-zA-Z]w{3,14}$。

在ASP應(yīng)用里,我們可以把密碼驗(yàn)證過(guò)程寫(xiě)成可重用的函數(shù),如下所示:

Function TestPassword(strPassword)

Dim re

Set re = new RegExp

re.IgnoreCase = false

re.global = false

re.Pattern = "^[a-zA-Z]w{3,14}$"

TestPassword = re.Test(strPassword)

End Function

下面我們把這個(gè)檢驗(yàn)密碼格式的正則表達(dá)式和自然語(yǔ)言描述對(duì)比著看看:

密碼的第一個(gè)字符必須是字母:正則表達(dá)式描述是“^[a-zA-Z]”,其中“^”表示字符串的開(kāi)始,連字符告訴RegExp匹配指定范圍的所有字符。

密碼最少4個(gè)字符且不超過(guò)15個(gè)字符:正則表達(dá)式描述是“{3,14}”。

密碼不能包含除字母、數(shù)字和下劃線以外的字符:正則表達(dá)式描述是“w”。

幾點(diǎn)說(shuō)明:{3,14}表示前面的模式匹配至少3個(gè)、但不超過(guò)14個(gè)的字符(加上第一個(gè)字符就成了4到15個(gè)字符)。注意花括號(hào)內(nèi)的語(yǔ)法要求極其嚴(yán)格,不允許在逗號(hào)的兩邊加入空格。如果加入了空格,它將對(duì)正則表達(dá)式的含義產(chǎn)生影響,導(dǎo)致密碼格式檢驗(yàn)時(shí)產(chǎn)生錯(cuò)誤。另外,上面的正則表達(dá)式末尾也沒(méi)有加上“$”字符。$字符使得正則表達(dá)式匹配字符串直至末尾,確保合法的密碼后面沒(méi)有加上任何其他字符。

類(lèi)似于密碼格式檢驗(yàn),檢查email地址的合法性也是一個(gè)很常見(jiàn)的問(wèn)題,用正則表達(dá)式進(jìn)行簡(jiǎn)單的email地址檢驗(yàn)可以實(shí)現(xiàn)如下:

<%

Dim re

Set re = new RegExp

re.pattern = "^w+@[a-zA-Z_]+?.[a-zA-Z]{2,3}$"

Response.Write re.Test("aabb@yahoo.com")

%>

------------------------------------------------------

二、提取HTML頁(yè)面的特定部分

從HTML頁(yè)面提取內(nèi)容所面臨的主要問(wèn)題是,我們必須尋找一種方法精確地識(shí)別出自己想要的那一部分內(nèi)容。例如,下面是一個(gè)顯示新聞標(biāo)題的HTML代碼片斷:

<table border="0" width="11%" class="Somestory">

<tr>

<td width="100%">

<p align="center">其他內(nèi)容...</td>

</tr>

</table>

<table border="0" width="11%" class="Headline">

<tr>

<td width="100%">

<p align="center">伊拉克戰(zhàn)爭(zhēng)?。?td>

</tr>

</table>

<table border="0" width="11%" class="Someotherstory">

<tr>

<td width="100%">

<p align="center">其他內(nèi)容...</td>

</tr>

</table>

觀察上述代碼,很容易看出新聞標(biāo)題由位于中間的表格顯示,它的class屬性設(shè)置為Headline。如果HTML頁(yè)面非常復(fù)雜,使用Microsoft IE從5.0開(kāi)始提供的一項(xiàng)附加功能可以只查看被選中部分頁(yè)面的HTML代碼,請(qǐng)?jiān)L問(wèn)http://www.microsoft.com/Windows/ie/WebAccess/default.ASP了解詳情。對(duì)于本例,我們假定這是唯一class屬性設(shè)置為Headline的表格?,F(xiàn)在我們要?jiǎng)?chuàng)建正則表達(dá)式,通過(guò)正則表達(dá)式找到這個(gè)Headline表格并把這個(gè)表格包含到自己的頁(yè)面中。首先是編寫(xiě)支持正則表達(dá)式的代碼:

<%

Dim re, strHTML

Set re = new RegExp ' 創(chuàng)建正則表達(dá)式對(duì)象

re.IgnoreCase = true

re.Global = false ' 第一次匹配之后結(jié)束查找

%>

下面考慮一下我們要提取的區(qū)域:在這里,我們要提取的是整個(gè)<table>結(jié)構(gòu),包括結(jié)束標(biāo)記和新聞標(biāo)題的文本。因此查找的起始字符應(yīng)該是<table>開(kāi)始標(biāo)記: re.Pattern = "<table.*(?=Headline)"。這個(gè)正則表達(dá)式匹配表格的開(kāi)始標(biāo)記,能夠返回開(kāi)始標(biāo)記直至“Headline”之間的所有內(nèi)容(換行除外)。下面是返回已匹配HTML代碼的方法:

' 把所有匹配的HTML代碼放入Matches集合

Set Matches = re.Execute(strHTML)

' 顯示所有匹配的HTML代碼

For Each Item in Matches

Response.Write Item.Value

Next

' 顯示其中一項(xiàng)

Response.write Matches.Item(0).Value

運(yùn)行這段代碼處理前面顯示的HTML片斷,正則表達(dá)式返回一次匹配的內(nèi)容如下: <table border="0" width="11%" class="。正則表達(dá)式中的“(?=Headline)”沒(méi)有獲取字符,所以不能看到表格class屬性的值。要獲取表格剩余部分的代碼也相當(dāng)簡(jiǎn)單: re.Pattern = "<table.*(?=Headline)(.|n)*?</table>"。其中:“(.|n)”后面的“*”匹配0個(gè)到多個(gè)任意字符;而“?”使得“*”匹配范圍最小化,即在找到表達(dá)式的下一部分之前匹配盡可能少的字符。</table>是表格的結(jié)束標(biāo)記。

“?”限制符非常重要,它防止了表達(dá)式返回其他表格的代碼。例如對(duì)于前面給出的HTML代碼片斷,如果刪除這個(gè)“?”則返回內(nèi)容將是:

<table border="0" width="11%" class="Headline">

<tr>

<td width="100%">

<p align="center">伊拉克戰(zhàn)爭(zhēng)?。?td>

</tr>

</table>

<table border="0" width="11%" class="Someotherstory">

<tr>

<td width="100%">

<p align="center">其他內(nèi)容...</td>

</tr>

</table>

返回的內(nèi)容不僅包含了Headline表的<table>標(biāo)記,而且還包含了Someotherstory表格,由此可以看出,這里的“?”是必不可少的。

本例假設(shè)了一些相當(dāng)理想化的前提。實(shí)際應(yīng)用中情況往往要復(fù)雜得多,特別是你對(duì)正在使用的源HTML代碼的編寫(xiě)沒(méi)有任何影響力時(shí),編寫(xiě)ASP代碼尤為困難。最有效的方法是,多花些時(shí)間分析待提取內(nèi)容附近的HTML,經(jīng)常地測(cè)試,確保提取出來(lái)的內(nèi)容正是自己所需要的。另外,應(yīng)當(dāng)重視并處理正則表達(dá)式不能匹配源HTML頁(yè)面任何內(nèi)容的情形。內(nèi)容的更新可能非??焖?,不要只因?yàn)閯e人改變了內(nèi)容的格式而讓自己的頁(yè)面出現(xiàn)低級(jí)可笑的錯(cuò)誤。

----------------------------------------------------

三、解析文本數(shù)據(jù)文件

數(shù)據(jù)文件的格式和種類(lèi)很多,XML文檔、結(jié)構(gòu)化文本甚至非結(jié)構(gòu)化文本都經(jīng)常成為ASP應(yīng)用的數(shù)據(jù)源。下面我們要看的一個(gè)例子是使用限定符的結(jié)構(gòu)化文本文件。限定符(比如引號(hào))表示字符串各個(gè)部分不可分割,即使字符串內(nèi)部包含把記錄分隔成字段的分隔符也一樣。

下面是一個(gè)簡(jiǎn)單的結(jié)構(gòu)化文本文件:

姓,名, 電話, 說(shuō)明

孫,悟空, 312 555 5656, ASP很好

豬,八戒, 847 555 5656, 我是電影制片人

這個(gè)文件非常簡(jiǎn)單,它的第一行是標(biāo)題,下面兩行是用逗號(hào)作為分隔符的記錄。要解析這個(gè)文件也很簡(jiǎn)單,只需先把文件分割成行(根據(jù)換行符號(hào)),然后把各個(gè)記錄按照字段分割。但是,如果我們?cè)谀硞€(gè)字段內(nèi)容中加入了逗號(hào):

姓,名, 電話, 說(shuō)明

孫,悟空, 312 555 5656, 我喜歡ASP,還有VB和SQL

豬,八戒, 847 555 5656, 我是電影制片人

解析第一個(gè)記錄時(shí)就會(huì)出現(xiàn)問(wèn)題,因?yàn)樵谥徽J(rèn)可逗號(hào)分隔符的解析器看來(lái)它的最后一個(gè)字段包含了兩個(gè)字段的內(nèi)容。為了避免出現(xiàn)這類(lèi)問(wèn)題,包含分隔符的字段必須用限定符包圍。單引號(hào)就是一種常用的限定符。把上面的文本文件加上單引號(hào)限定符之后,它的內(nèi)容如下所示:

姓,名, 電話, 說(shuō)明

孫,悟空, 312 555 5656, '我喜歡ASP,還有VB和SQL'

豬,八戒, 847 555 5656, '我是電影制片人'

現(xiàn)在我們能夠肯定哪一個(gè)逗號(hào)是分隔符、哪一個(gè)逗號(hào)是字段內(nèi)容了,即只需把引號(hào)內(nèi)部出現(xiàn)的逗號(hào)視為字段的內(nèi)容。接下來(lái)我們要做的就是實(shí)現(xiàn)一個(gè)正則表達(dá)式解析器,由這個(gè)解析器確定何時(shí)根據(jù)逗號(hào)分割字段、何時(shí)把逗號(hào)視為字段內(nèi)容。

這里的問(wèn)題與大多數(shù)正則表達(dá)式所面臨的略有不同。通常我們查看的是文本的一小部分,看看它是否能夠和正則表達(dá)式匹配。但在這里,只有考慮了整行文本之后我們才能可靠地判斷出哪些內(nèi)容位于引號(hào)之內(nèi)。

下面是一個(gè)說(shuō)明該問(wèn)題的例子。從某個(gè)文本文件隨意抽取半行內(nèi)容,得到:1, 沙灘, 黑色, 21, ', 狗, 貓, 鴨子, ', 。在這個(gè)例子中,因?yàn)椤?”的左邊還有其他數(shù)據(jù),要解析清楚它的內(nèi)容是極其困難的。我們不知道這個(gè)數(shù)據(jù)片斷的前面有多少單引號(hào),從而也就無(wú)法判斷哪些字符位于引號(hào)之內(nèi)(在引號(hào)之內(nèi)的文本解析時(shí)不能分割)。如果這個(gè)數(shù)據(jù)片斷之前有偶數(shù)個(gè)(或者沒(méi)有)單引號(hào),那么“', 狗, 貓, 鴨子, '”是用引號(hào)界定的字符串且不可分割。如果前面的引號(hào)數(shù)量是奇數(shù),那么“1, 沙灘, 黑色, 21, '”是某個(gè)字符串的結(jié)束部分且不可分割。

因此,正則表達(dá)式必須分析整行文本,全面考慮出現(xiàn)了多少引號(hào)才能確定字符是處在引號(hào)對(duì)的內(nèi)部還是外部,即:,(?=([^']*'[^']*')*(?![^']*'))。這個(gè)正則表達(dá)式首先找到一個(gè)引號(hào),然后繼續(xù)查找并保證逗號(hào)后面的單引號(hào)數(shù)量或者是偶數(shù)、或者是0。該正則表達(dá)式以下面這個(gè)判斷為基礎(chǔ):如果逗號(hào)后面的單引號(hào)數(shù)量是偶數(shù),那么這個(gè)逗號(hào)位于字符串之外。下表給出了更詳細(xì)的說(shuō)明:

, 尋找一個(gè)逗號(hào)

(?= 繼續(xù)向前查找以匹配下面這個(gè)模式:

( 開(kāi)始一個(gè)新的模式

[^']*' [非引號(hào)字符]0個(gè)或者多個(gè),然后是一個(gè)引號(hào)

[^']*'[^']*) [非引號(hào)字符]0個(gè)或者多個(gè),然后是一個(gè)引號(hào)。結(jié)合前面的內(nèi)容之后它匹配引號(hào)對(duì)

)* 結(jié)束模式并匹配整個(gè)模式(引號(hào)對(duì))0次或者多次

(?! 向前查找,排除此模式

[^']*' [非引號(hào)字符]0個(gè)或者多個(gè),然后是一個(gè)引號(hào)

) 結(jié)束模式

下面是一個(gè)VBScript函數(shù),它接受一個(gè)字符串參數(shù),根據(jù)字符串中的逗號(hào)分隔符、單引號(hào)限定符分割字符串,返回結(jié)果數(shù)組:

Function SplitAdv(strInput)

Dim objRE

Set objRE = new RegExp

' 設(shè)置RegExp對(duì)象

objRE.IgnoreCase = true

objRE.Global = true

objRE.Pattern = ",(?=([^']*'[^']*')*(?![^']*'))"

' Replace方法用chr(8)替換我們要用到的逗號(hào),chr(8)即b

' 字符,b在字符串中出現(xiàn)的可能極為微小。

' 然后我們根據(jù)b把字符串分割保存到數(shù)組

SplitAdv = Split(objRE.Replace(strInput, "b"), "b")

End Function

總而言之,用正則表達(dá)式解析文本數(shù)據(jù)文件具有高效、縮短開(kāi)發(fā)時(shí)間的優(yōu)點(diǎn),能夠節(jié)省大量分析文件、根據(jù)復(fù)雜的條件提取有用數(shù)據(jù)的時(shí)間。在一個(gè)迅速發(fā)展的環(huán)境中仍會(huì)有許多傳統(tǒng)的數(shù)據(jù)可資利用,掌握如何構(gòu)造高效的數(shù)據(jù)分析例程將是一種寶貴的技能。

-------------------------------------------------------------------

四、字符串替換

在最后一個(gè)例子中我們要看看VBScript正則表達(dá)式的替換功能。ASP經(jīng)常用于動(dòng)態(tài)地格式化從各種數(shù)據(jù)源獲得的文本。利用VBScript正則表達(dá)式的強(qiáng)大功能,ASP能夠動(dòng)態(tài)地改變匹配的復(fù)雜文本。通過(guò)加入HTML標(biāo)記突出顯示部分單詞就是一種常見(jiàn)的應(yīng)用,比如突出顯示搜索結(jié)果中的搜索關(guān)鍵詞。

為說(shuō)明實(shí)現(xiàn)方法,下面我們來(lái)看一個(gè)突出顯示字符串中所有“.NET”的例子。這個(gè)字符串可以從任何地方獲得,比如數(shù)據(jù)庫(kù)或者其他Web網(wǎng)站。

<%

Set regEx = New RegExp

regEx.Global = true

regEx.IgnoreCase = True

' 正則表達(dá)式模式,

' 尋找任何結(jié)尾為“.NET”的單詞或者URL。

regEx.Pattern = "(b[a-zA-Z._]+?.NETb)"

' 用于測(cè)試替換功能的字符串

strText = "微軟建立了一個(gè)新網(wǎng)站www.ASP.NET。"

' 調(diào)用正則表達(dá)式的Replace方法

' $1表示把匹配的文本插入當(dāng)前位置

Response.Write regEx.Replace(strText, _

"<b style='color: #000099; font-size: 18pt'>$1</b>")

%>

這個(gè)例子中有幾個(gè)重要的地方必須注意。整個(gè)正則表達(dá)式被放入了一對(duì)圓括號(hào)中,它的作用是截取所有匹配的內(nèi)容供以后使用,這些內(nèi)容在替換文本中通過(guò)$1引用。類(lèi)似的截取每次替換可以使用多達(dá)9個(gè),分別通過(guò)$1到$9引用。正則表達(dá)式的Replace方法和VBScript本身的Replace函數(shù)不同,它只需要兩個(gè)參數(shù):被搜索的文本,替換用的文本。

在這個(gè)例子中,為了突出顯示搜索到的“.NET”字符串,我們用粗體標(biāo)記以及其他樣式屬性來(lái)包圍這些字符串。使用這種搜索和替換技術(shù),我們能夠方便地為網(wǎng)站搜索程序加上突出顯示搜索關(guān)鍵詞的功能,或者自動(dòng)為頁(yè)面中出現(xiàn)的關(guān)鍵詞加上指向其他頁(yè)面的鏈接。

結(jié)束語(yǔ)

希望本文介紹的幾種正則表達(dá)式技巧對(duì)你在何時(shí)、如何應(yīng)用正則表達(dá)式有所啟發(fā)。雖然本文的例子用VBScript編寫(xiě),但在ASP.NET中正則表達(dá)式同樣也大有用武之地,它是服務(wù)器端控件表單檢驗(yàn)的主要機(jī)制之一,而且通過(guò)System.Text.RegularExpressions命名空間導(dǎo)出到了整個(gè).NET框架之中。

更多信息請(qǐng)查看IT技術(shù)專(zhuān)欄

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:正則表達(dá)式應(yīng)用技巧四則
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢(xún)回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門(mén)公布的正式信息和咨詢(xún)?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽(tīng)報(bào)名

  • 報(bào)班類(lèi)型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢(xún) | 簡(jiǎn)要咨詢(xún)須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專(zhuān)用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢(xún)關(guān)注公眾號(hào):hfpxwx
咨詢(xún)QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專(zhuān)用圖標(biāo)