當(dāng)我們在瀏覽網(wǎng)頁的時候,常常會在瀏覽器中鍵入網(wǎng)址,如 www.cctv.com,然后網(wǎng)址就會被轉(zhuǎn)換成相應(yīng)的 IP 地址,其的結(jié)果可能會是“123.0.111.108”,每一個部分都是一個小于256的非負(fù)整數(shù)。嚴(yán)格地講,像007這樣的內(nèi)容也是允許作為 IP 地址的一部分的,但在一般情況下,前面的“0”是不需要的。
在對 IP 地址格式的概念簡單了解之后,我們就來做一個驗證 IP 地址的實驗。首先構(gòu)造一個能夠匹配三位數(shù)字的正則表達(dá)式 /d{1,3} ,它所匹配的結(jié)果就是 123 . 0 . 111 . 108 。注意,間隔的小數(shù)點并不作為匹配的結(jié)果。接下來,從結(jié)果的四組數(shù)字上可以看出,除了第一組數(shù)字之外,剩余的三組數(shù)字前面都有一個“小數(shù)點”,所以,我們可以構(gòu)造一個新的表達(dá)式 /d{1,3}(/./d{1,3}){3} 來匹配整個字符串,第一個 /d{1,3} 匹配的是第一組數(shù)字,后面的內(nèi)容匹配的是剩余的三組數(shù)字,并且每組數(shù)字前面必須要有一個“小數(shù)點”,因為“小數(shù)點”在正則表達(dá)式中可以代表任意字符,所以在使用時需要進(jìn)行轉(zhuǎn)義。
在第一章概述的內(nèi)容中我們就了解到,正則表達(dá)式主要用于字符串匹配,而對于邏輯校驗它就不太擅長了,不過為了更好地掌握正則表達(dá)式應(yīng)用技巧,在這里我們?nèi)杂盟鲆淮芜壿嬌系男r灒螅覀冊倏匆粋€更為合理并且簡單的校驗方法。之前我們已經(jīng)構(gòu)造了一個能夠簡單驗證 IP 地址的正則表達(dá)式了,下面要做的就是邏輯校驗,更確切地說,就是保證每組數(shù)字處于 0 至 255 之間即可。從范圍上看,每組數(shù)字最大位數(shù)也就是三位,最大值為 255。因此,我們需要先構(gòu)造一個 200 至 255 的三位數(shù)樣式 2([0-4]/d|5[0-5]) ,然后構(gòu)造出一個匹配大于等于 0 小于 200 的樣式 [0-1]?/d{1,2} 。現(xiàn)在把兩部分樣式合并起來 2([0-4]/d|5[0-5])|[0-1]?/d{1,2} ,這樣就可以滿足每組的數(shù)字驗證,最后統(tǒng)一整理就是 (2([0-4]/d|5[0-5])|[0-1]?/d{1,2})(/.(2([0-4]/d|5[0-5])|[0-1]?/d{1,2})){3} 。這個樣式與之前構(gòu)造的 /d{1,3}(/./d{1,3}){3} 類似,只是將不含有數(shù)字范圍的 /d 替換成含有數(shù)字范圍驗證的 2([0-4]/d|5[0-5])|[0-1]?/d{1,2} 。
現(xiàn)在,我們再嘗試一種較為合理而且簡單的編程實現(xiàn)方法,首先用正則表達(dá)式 /. 分割成四組數(shù)字,用程序驗證每組數(shù)字的范圍,判斷它們是否存在于 0 至 255 之間,以下是 VB.Net 所實現(xiàn)的代碼:
-
Imports System
.
Text
.
RegularExpressions
-
-
Module
ModuleForTest
-
-
Sub
Main
()
-
Try
-
Console
.
WriteLine
(
"請輸入要驗證的IP地址:"
)
-
Dim
userInput
As
String
=
System
.
Console
.
ReadLine
()
-
If
Regex
.
IsMatch
(
userInput
,
"^[0-9]{1,3}(/.[0-9]{1,3}){3}$"
)
Then
-
Dim
ipSections
As
String
() =
Regex
.
Split
(
userInput
,
"/."
)
-
For Each
ipNumber
As
String
In
ipSections
-
Dim
tempNumber
As
Integer
=
Convert
.
ToInt32
(
ipNumber
)
-
If
tempNumber
<
0
OrElse tempNumber
>
256
Then
-
Console
.
WriteLine
(
"非法IP地址!"
)
-
Exit Sub
-
End If
-
Next
-
Console
.
WriteLine
(
"合法IP地址!"
)
-
Else
-
Console
.
WriteLine
(
"非法IP地址!"
)
-
End If
-
Catch ex
As
Exception
-
Console
.
WriteLine
(
ex
.
Message
)
-
Finally
-
Console
.
ReadLine
()
-
End
Try
-
End Sub
-
-
End Module
接下來我們再來看一個關(guān)于文件打印的頁碼設(shè)置的校驗例子。從下圖可以看出,打印范圍可以用以逗號分隔的多個具體的頁碼值來表現(xiàn),也可以用以逗號分隔的多個頁碼范圍來表現(xiàn),或者是將頁碼值與頁面范圍進(jìn)行的組合來表現(xiàn);而對于頁碼的內(nèi)容的設(shè)置,則可以通過頁碼和頁碼加小節(jié)組成。在這里我們先從簡單的頁碼設(shè)置入手,然后再處理比較復(fù)雜的設(shè)置。
對于具體的單一頁碼來說,直接利用數(shù)字表達(dá)式 /d+ 來表示就可以了,但頁碼不可能從零開始,所以首位應(yīng)該用 1 至 9 表示,而后續(xù)的數(shù)字則不受零的限制,可以采用 /d 來表示,所以修改后的非零自然數(shù)樣式應(yīng)該為 [1-9]/d* ;而對于頁碼范圍來說,應(yīng)該由一對具體的頁碼來表現(xiàn),再在中間放一個標(biāo)示范圍的標(biāo)識符“-”,最終構(gòu)造出來的樣式就應(yīng)該為 [1-9]/d*-[1-9]/d* 。現(xiàn)在,我們把這兩個樣式結(jié)合起來,組合出我們想要的具體頁碼與頁碼范圍的混合樣式 ([1-9]/d*|[1-9]/d*-[1-9]/d*)(,([1-9]/d*|[1-9]/d*-[1-9]/d*))* 。先來分析下逗號之前的樣式 ([1-9]/d*|[1-9]/d*-[1-9]/d*) ,它所匹配的內(nèi)容就是一個單一的具體的頁碼或是一個頁碼范圍,而在后面的重復(fù)樣式中,除了逗號之外,其余的樣式前面的完全一致,這是便于后續(xù)添加多個這樣的單一的具體頁碼或頁碼范圍。現(xiàn)在構(gòu)造出來的樣式就可以完全滿足數(shù)字表現(xiàn)形式的頁碼或頁碼范圍組合了。
接下來我們繼續(xù)構(gòu)造頁碼加小節(jié)的組合樣式。從圖中我們可以看出,單一的頁碼或單一的小節(jié),都是用字母加數(shù)字組合,如第一頁為 p1,第二頁為 p2,依此類推,小節(jié)的表述形式與頁碼類似,只是字母為 s,第一節(jié)為 s1,第二節(jié)為 s2……這樣一來,頁碼加小節(jié)的組合就是 p[1-9]/d*s[1-9]/d* ,同數(shù)字頁碼表現(xiàn)形式的規(guī)則一樣,我們重復(fù)利用這個表達(dá)式,構(gòu)造一個完整的樣式就應(yīng)該是 (p[1-9]/d*s[1-9]/d*|p[1-9]/d*s[1-9]/d*-p[1-9]/d*s[1-9]/d*)(,(p[1-9]/d*s[1-9]/d*|p[1-9]/d*s[1-9]/d*-p[1-9]/d*s[1-9]/d*))* ,逗號之前是匹配單一的頁碼與小節(jié),或是頁碼與小節(jié)的范圍,逗號以及逗號之后部分利用“*”使這種規(guī)則延續(xù)下去。
通過第一章的內(nèi)容我們可以知道,正則表達(dá)式并不擅長邏輯處理,所以我們構(gòu)造出的頁碼表達(dá)式也僅僅是對形式的一種約束,其中并不含有任何邏輯,如果想加入邏輯功能,在必要的情況下就得配合一段程序代碼了。在這里,我們暫時不考慮頁碼之間空白字符問題并且假定頁碼出現(xiàn)的順序必須從小到大,然后用下面這段 Javascript 程序,配合第一種樣式來驗證這個規(guī)則。
-
<
script
language
=
"javascript"
type
=
"text/javascript"
>
-
function
isValidPageRangeForPrint
{
-
var
pageRangeText
=
document
.
getElementById
(
"page_range"
).
value
;
-
// 是否錄入頁碼范圍
-
if
(!
pageRangeText
) {
-
return false
;
-
}
-
// 是否滿足頁碼范圍的格式
-
if
(!/
^
([
1
-
9
]
/d
*|[
1
-
9
]
/d
*-[
1
-
9
]
/d
*)(,([
1
-
9
]
/d
*|[
1
-
9
]
/d
*-[
1
-
9
]
/d
*))*
$
/.
test
(
pageRangeText
)) {
-
return false
;
-
}
-
// 是否滿足頁碼從小到大的邏輯規(guī)則
-
var
regexForSinglePage
= /[
1
-
9
]
/d*/
;
-
var
matchResult
=
pageRangeText
.
match
(/[
1
-
9
]
/d
*|[
1
-
9
]
/d
*-[
1
-
9
]
/d*/
);
-
var
pageEnumCount
=
0
;
-
var
pageContainer
=
new
Object
();
-
// 將所有出現(xiàn)的頁碼按照出現(xiàn)的順序保存到pageContainer中
-
for
(
var
i
=
0
;
i
<
matchResult
.
length
;
i
++) {
-
if
(
regexForSinglePage
.
test
(
matchResult
[
i
])) {
-
// 保存單一頁碼
-
pageContainer
[
""
+
pageEnumCount
++] =
matchResult
[
i
];
-
}
else
{
-
// 保存起始頁碼與結(jié)束頁碼
-
var
pagesForRange
=
matchResult
[
i
].
split
(/-/);
-
pageContainer
[
""
+
pageEnumCount
++] =
pagesForRange
[
0
];
-
pageContainer
[
""
+
pageEnumCount
++] =
pagesForRange
[
1
];
-
}
-
}
-
// 對pageContainer中的頁碼進(jìn)行驗證,后續(xù)的頁碼必須大于前方的頁碼
-
while
(
pageEnumCount
-- >
0
) {
-
if
(
pageContainer
[
pageEnumCount
] <
pageContainer
[
pageEnumCount
-
1
]) {
-
// 后續(xù)頁碼小于前方頁碼時
-
return false
;
-
}
-
}
-
return true
;
-
}
-
</
script
>
<!-- InstanceEndEditable -->
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
