直播中
正則表達(dá)式的簡(jiǎn)單介紹
正則表達(dá)式大部分都是來(lái)自與Unix世界的需要。
在Unix中許多編程語(yǔ)言幾乎整個(gè)都是圍繞著正則表達(dá)式進(jìn)行的(例如Perl, Python, Tcl)
但是令人感到奇怪的是正則表達(dá)式好象是最近才使用在Windows系列中的,
特別是大量的使用在腳本語(yǔ)言中,例如JavaScript和VBScript,
盡管你也可以將它們使用在Visual Basic或則Java中,但是顯然它們似乎在
腳本語(yǔ)言中更加有吸引力。也許是這個(gè)緣故把,大家平時(shí)似乎都很少使用正則表達(dá)式把。
使用正則表達(dá)式,你可以根據(jù)你想查詢的內(nèi)容建立一個(gè)匹配模板(英文叫pattern)
一旦你使用正則表達(dá)式建立了一個(gè)模板,你就可以使用它來(lái)測(cè)試你的字符串了,
使用它可以完成很多功能:
例如判斷一個(gè)字符串是否在另外一個(gè)字符串中(或則在另外一個(gè)字符串中的什么位置)
例如使用一個(gè)字符串來(lái)替換另外一個(gè)字符串
例如返回所有滿足模板條件的字符串列表
例如。。。等等等等
上面我介紹了有關(guān)正則表達(dá)式的基本概念,有關(guān)它的詳細(xì)說(shuō)明和語(yǔ)法可以查閱MSDN和
JavaScript中的有關(guān)幫助。
在VB中如果你想引用正則表達(dá)式的話,你需要在項(xiàng)目中引用"Microsoft VBScript Regular Expressions"。但是如果你要是使用腳本的話就不必要了,因?yàn)樵谀_本里面這已經(jīng)是一個(gè)
內(nèi)在的對(duì)象供你引用了。
當(dāng)然你需要在你的機(jī)器上安裝IE4以上羅。
這個(gè)對(duì)象(在JavaScript中)叫RegExp
下面還是讓代碼來(lái)說(shuō)明問題把,現(xiàn)在假設(shè)你想查看一個(gè)文擋里面是否包含一個(gè)特定的
字符串(例如"regular expressions")
代碼見下:
代碼使用VB寫成。
Public Function IsTermInDocument(filePath As String,_
expr As String) As Boolean
Dim fs As FileSystemObject
Dim ts As TextStream
Dim re As RegExp
Dim text As String
Set fs = New FileSystemObject
Set ts = fs.OpenTextFile(filePath, ForReading)
text = ts.ReadAll
Set re = New RegExp
re.Pattern = expr
IsTermInDocument = re.Test(text)
End Function
Debug.print IsTermInDocument("c:\bin\myPage.htm",_
"regular expression")
上面的那個(gè)函數(shù)將根據(jù)文擋里面是否有滿足條件的字符串返回True/False.
注意我加粗的部分:
第一句是建立一個(gè)正則表達(dá)式的對(duì)象
第二句是指定該正則表達(dá)式的模板
第三句就是根據(jù)模板執(zhí)行查詢了
呵呵,如果正則表達(dá)式的功能僅僅是這么簡(jiǎn)單的話,也許你會(huì)說(shuō)
VB中的instr()不就能夠代替了嗎?
但是,在進(jìn)行XML的數(shù)據(jù)格式化的時(shí)候,對(duì)字符串的處理遠(yuǎn)比這個(gè)復(fù)雜得多。
例如:假設(shè)你要確保你要驗(yàn)證的字段中是否包含一個(gè)well-formed的zip編碼
(well-formed意味著它是一個(gè)有效的編碼,
也許它對(duì)于某個(gè)給定的地方或則區(qū)域或則國(guó)家又是無(wú)效的
這種界于well-formed和valid的表達(dá)式將是本文里面討論的重點(diǎn))
如果你要是使用VB來(lái)進(jìn)行這種判斷的話將非常的難看
你需要判斷是否表達(dá)式有5位或則10位數(shù)字,或則是否為字母,
然后第6位字母又必須得是一個(gè)破則號(hào)
但是如果是使用正則表達(dá)式的話,將會(huì)是這樣的簡(jiǎn)單:
Set IsZipCode = New RegExp
IsZipCode.Pattern = "^\d{5}(-\d{4})?$"
if IsZipCode.test("32545-2198") then
下面將簡(jiǎn)單解釋一下其中模板的含義:
^ 說(shuō)明在這個(gè)表達(dá)式之前沒有任何其它的字符串,
意味著要驗(yàn)證的表達(dá)式不是某個(gè)字符串中間的一部分,而是它的開頭
\d 表示下一個(gè)字符必須是0-9中的一個(gè)數(shù)字
\d{5} 并且必須是連著的5個(gè)數(shù)字
-\d{4} 4個(gè)數(shù)字必須出現(xiàn)在字符"-"的后面
(-\d{4})? 這4個(gè)數(shù)字是可選的,即可有也可以沒有
$ 這個(gè)表達(dá)式后面應(yīng)該不會(huì)再有其它的什么東西了
最有意思的是一旦你定義好了這么一個(gè)模板,你就可以將它使用在
任何其它的正則表達(dá)式對(duì)象中,而不需要再重新建立一個(gè)正則表達(dá)式對(duì)象了了。
使用這個(gè)辦法,你甚至可以把一個(gè)近2000行代碼的JavaScript程序
減少到只有幾百行,設(shè)置當(dāng)你把一些模板組合在一起的時(shí)候,就能夠完成
正則表達(dá)式本來(lái)不可能完成的東東了。
下面我再舉一個(gè)用來(lái)驗(yàn)證數(shù)據(jù)有效性的例子:
例如你現(xiàn)在想驗(yàn)證一個(gè)電話號(hào)碼數(shù)據(jù)是否有效
對(duì)于通用一個(gè)電話號(hào)碼一般下面這幾種寫法都是有效的:
(800)555-1212
1(800) 555-1212
1-800-555-1212
1.800.555.1212
等等.
如果你使用腳本來(lái)寫一段滿足上面所有要求的代碼將非常的復(fù)雜。
但是如果你使用正則表達(dá)式的話,將非常的簡(jiǎn)單,只有下面這兩句代碼:
Set IsPhoneNumber=new RegExp
IsPhoneNumber.pattern="^[01]?\s*[\(\.-]?(\d{3})[\)\.-]?\s*(\d{3})[\.-](\d{4})$"
你可以仔細(xì)體會(huì)上面這個(gè)代碼的意義。
首先它驗(yàn)證第一個(gè)字符是否為0或則是否為1或則根本就沒有。
然后再進(jìn)行下面的驗(yàn)證,大家可以自己琢磨其它部分的意思把,呵呵。
查詢和替換數(shù)據(jù)
當(dāng)然,驗(yàn)證數(shù)據(jù)的有效性僅僅是它能夠做的一件小事而已,
但是更有用的是:如果你能夠把上面那么多種電話號(hào)碼的表達(dá)方式轉(zhuǎn)換
成一種統(tǒng)一的方式顯示出來(lái)。
例如我要把上面的電話號(hào)碼格式化成XML中的一個(gè)片段如下:
<phoneNumber>
<areacode>123</areacode>
<exchange>456</exchange>
<local>7890</local>
</phoneNumber>
這時(shí)的電話號(hào)碼的模板分成三個(gè)部分:
(\d{3}), (\d{3}), (\d{4}), 分別表示area code, exchange, 和local number
. 在正則表達(dá)式中,正則解釋器會(huì)自動(dòng)
將匹配的字符賦值給變量 $1, $2, $3,等.
這樣你使用下面的代碼就能夠?qū)崿F(xiàn)
re.Replace("1(352)351-4159", "<phoneNumber><areacode>$1</areacode><exchange>$2</exchange><local>$3</local></phoneNumber>")
如果你覺得這個(gè)Replace使用起來(lái)很不舒服的話,下面將給出一個(gè)
類似與VB中的Replace并且擴(kuò)展了它的函數(shù)
Public Function Replacex(sourceStr as String, oldStr as _
String, newStr as String, optional ignoreCase as _
Boolean = False,optional isGlobal as Boolean = True)
Dim re As New RegExp
re.Pattern = oldStr
re.Global = isGlobal
re.IgnoreCase = ignoreCase
Replacex = re.Replace(sourceStr, newStr)
End Function
下面給出使用它的一些例子:
Debug.Print Replacex("This is a test","is","at")
--> "That at a test"
最精彩的還是使用正則表達(dá)式了
Debug.Print Replacex("This is a test","\ws","at")
--> "That at a tatt"
甚至還可以這樣
Debug.Print Replacex("This is a test","(\ws)","at$1")
--> "Thatis atis a tatist"
正則表達(dá)式的replace方法還有兩個(gè)參數(shù)。
在默認(rèn)的情況時(shí)正則表達(dá)式在找到了一個(gè)滿足條件的時(shí)候就會(huì)停下來(lái)
但是如果你要是將isGlobal參數(shù)設(shè)置為True的話,它就會(huì)全文替換
在默認(rèn)的情況下正則表達(dá)式是區(qū)分大小寫的
但是如果你將ignoreCase設(shè)置為False的話,它將不區(qū)分大小寫
獲得XML的節(jié)點(diǎn)
現(xiàn)在,我們將一起來(lái)看看正則表達(dá)式在XML中是如何運(yùn)用的。
首先,在Microsoft's XML 2.0解釋器里面有兩大難題:
第一, 這個(gè)XML解釋器在裝載XML文擋的時(shí)候必須要保證入口
滿足定義在DTD的范圍之內(nèi)。這是一個(gè)大麻煩,因?yàn)榫湍壳暗那闆r來(lái)看,
XML更改頻繁,不時(shí)會(huì)多出一些標(biāo)準(zhǔn),不時(shí)又會(huì)產(chǎn)生新的標(biāo)志。
第二,如果使用XSL的話不能夠操縱DTD,甚至當(dāng)你使用腳本語(yǔ)言也是一件很費(fèi)力的事情。
經(jīng)常要做的是你需要在XSL使用XSL的結(jié)構(gòu)表達(dá)式中設(shè)置一些變量,例如
瀏覽器的類型或則ASP的參數(shù)呀
這時(shí)你可以使用正則表達(dá)式來(lái)解決這些問題。
當(dāng)你想獲取一個(gè)XML元素的時(shí)候,也許這個(gè)對(duì)象有可能并不是你想要的東東。
例如:假設(shè)一個(gè)很簡(jiǎn)單的XML結(jié)構(gòu),一個(gè)圖書目錄.
XML的代碼如下:
<catalog>
<book>
<title>XML for Beginners</title>
<author>Fred Fnord</author>
<description>A book on XML for programming neophytes.</description>
</book>
<book>
<title>Pair-O-Dice Lost</title>
<author>U. Wajer</author>
<description>Techniques for throwing the game.</description>
</book>
<book>
<title>The Fields of Oberon</title>
<author>Alan Landis</author>
<description>The wee folk are back, and they aren't happy.</description>
</book>
<book>
<title>Distributed Computing on a Budget</title>
<author>Fred Fnord</author>
<description>Using XML and related techniques for managing distributed applications.</description>
</book>
</catalog>