首頁 > 軟體

正規表示式匹配ip地址超詳細講解

2022-12-03 14:01:10

一、正則匹配基本知識及概念

在練習之前,需要大家知道一些基本知識,如果有一定基礎的可以跳過該步驟,直接往下看。

正規表示式-字元類

[abc]:代表a或者b,或者c字元中的一個。
[^abc]:代表除a,b,c以外的任何字元。
[a-z]:代表a-z的所有小寫字元中的一個。
[A-Z]:代表A-Z的所有大寫字元中的一個。
[0-9]:代表0-9之間的某一個數位字元。
[a-zA-Z0-9]:代表a-z或者A-Z或者0-9之間的任意一個字元。
[a-dm-p]:a 到 d 或 m 到 p之間的任意一個字元。

正規表示式-邏輯運運算元

&&:並且
| :或者(可以省略)

正規表示式-預定義字元

“.” : 匹配任何字元。
“d”:任何數位[0-9]的簡寫;
“D”:任何非數位[^0-9]的簡寫;
“s”: 空白字元:[ tnx0Bfr] 的簡寫
“S”: 非空白字元:[^s] 的簡寫
“w”:單詞字元:[a-zA-Z_0-9]的簡寫
“W”:非單詞字元:[^w]

正規表示式-數量詞

x? : 0次或1次
x* : 0次到多次
x+ : 1次或多次
X{n} : 恰好n次
X{n,} : 至少n次
X{n,m}: n到m次(n和m都是包含的,最少n次,最多m次。

二、ip地址匹配

題目要求:使用正規表示式匹配192.11.23.69

須知:ip地址的範圍為0.0.0.0-255.255.255.255

接下來我們直接進入正題吧!在我們看到題目的第一眼,大家可能覺得很簡單,這不就用d{1,3}.d{1,3}.d{1,3}.d{1,3}

這裡我們可以看到使用上述表示式的確匹配成功。

雖然完成了我們的題目要求,有些細心的夥伴會發現,用紅色標註出來的部分,重複了三遍,是不是我們可以用分組的方式來簡化表示式並完成題目要求。我們把上面的匹配表示式換成分組之後的樣子,即(d{1,3}.){3}d{1,3}

表示式講解:(d{1,3}.) 匹配我們前三段的ip地址和’.‘,因為第四段ip地址最後面不能有’.',如果我們使用在同一個分組去匹配就會出現錯誤情況,而d{1,3}剛好匹配我們最後一段ip地址

匹配效果如下:

 匹配同樣成功,該模式有什麼不對的地方嗎?從語法上看,完全正確,也達到了我們的題目要求,可是我們有沒有注意到,我們日常生活中所用的ip地址每一位都是在0-255之間,但是我們上面寫的表示式會匹配0-999之間的所有ip地址,如果在未來的工作中,有這樣的需求,要匹配所有合法的ip地址,那麼我們上面所寫的正規表示式是不是就不符合要求了,這裡就需要我們使用子表示式的巢狀(注意:有一點很重要。通過上面的例子,我們發現,寫一個能夠匹配預期內容的正規表示式其實並不難,但是寫一個能夠考慮到所有可能場景,確保將不需要匹配的內容排除在外的正規表示式就困難多了)

 所以我將上面的表示式又改進了一下(這裡用到了子表示式的巢狀,如果不懂的小夥伴可以先看一下基本概念再來看接下來的內容)。我們發現當ip地址僅有一位或者兩位的時候(即1.1.1.1 or 11.11.11.11),用(d{1,2}.)就可以完成匹配,當ip地址為三位的時候,會有這麼兩種情況(這裡留下個疑問,考慮到初學者可能犯錯的情況)?

1:ip地址開頭為1的時候,我們後面的兩位每一位的範圍都在0-9之間,而d這個元字元剛好滿足了我們的要求,所以使用(1d{2}.)就滿足了我們在100-199ip地址的匹配,這個其實還相對簡單,接下來就是200-255之間ip地址的匹配了,有些同學可能會想,我們可以使用匹配100-199的表示式來實現對200-255ip地址的匹配,即(2d{2}.)這樣的表示式來實現,可是這樣會把256-299之間的ip地址匹配到,違反了我們的意願,所以我改良了一下表示式(2[0-5]{2}.]),這樣就只會匹配到200-255之間的ip地址,既然子表示式都寫好了,就讓我們來實踐看看效果吧!

表示式為:((1d{2}.)|(2[0-5]{2}.)|(d{1,2}.)){3}((d{1,2})|(1d{2})|(2[0-5]{2}))),夥伴們可以一起實踐一下!

匹配成功,可是再寫出這個表示式,我們要測試某些特殊情況是否不在我們的匹配範圍內,於是我發現了以下兩個比較重要的問題。

第一種:

合法ip地址匹配錯誤

第二種:

非法ip地址匹配成功

為什麼會出現上面的情況?

當我們覺得表示式很完美的時候,雖然256超出匹配範圍,但是因為(d{1,2}.)的影響,使得我們的非法表示式也匹配成功,本來192.11.23.200為合法表示式,卻只匹配到了98.11.23.200,請大家看我用紅色箭頭標註的地方,會不會跟我們子表示式的順序有關呢?那好,我來改變一下順序,我們將(d{1,2}.)放到了最後,防止出現錯誤匹配

改變匹配順序後的表示式為:
( ( (2[0-5]{2}.)|(1d{2}.)|(d{1,2}.)){3}((1d{2})|(2[0-5]{2})|(d{1,2})))

果然,第一種情況我們是因為子表示式順序的原因,導致匹配錯誤。

可是第二種情況使用改變順序的表示式,依然會出現以上問題(這裡也就印證了上文提到的那些話,要想寫出一個符合規範的表示式就很困難)。

於是這裡的^就起到了作用,我們可以把第一個子表示式單另拉出來加上^表示第一段ip地址開頭為(d{1,2}),這樣剛好避免了我們如上的情況,效果如下:

可以看到非法ip不在我們的匹配當中。

其實寫到這裡大家是不是感覺已經大功告成了?回答:No

(2[0-5]{2})這個表示式能否匹配239這個ip呢?不知道有沒有細心的小夥伴發現

所以最終正確的表示式應該為:
(^((2[0-4]d.)|(25[0-5].)|(1d{2}.)|(d{1,2}.))((2[0-5]{2}.)|(1d{2}.)|(d{1,2}.){2})((1d{2})|(2[0-5]{2})|(d{1,2})))

在這裡可以跟大家說一下,是否可以使用$來避免我們上述第一種問題,有興趣的可以嘗試一下

附正規表示式匹配IP地址小結

1. IP段都表示一個位元組,即只能在 0~255之間。

所以一個正確的IP應該是:(0~255) .(0~255) .(0~255) .(0~255)

通過觀察可以發現可以將整個IP分為兩部分匹配,即:(0~255) 和 .(0~255) 3次

2. 0~255可以分兩部分匹配 0~199 和 200~255

a) 0~199 正規表示式為 [0-1]?d{1,2}

[0-1]? 表示匹配 0或1一次或零次

d 表示匹配任意一個十進位制數位,即 0~9

{1,2} 表示匹配上一個元素至少一次,最多兩次,這裡就是 d一次或兩次

b) 200~255 正規表示式為 2((5[0-5])|([0-4]d)),又可以分為兩部分 200~249 和 250~255

2 表示必須以2開頭

5[0-5] 表示匹配 50~55 之間的數

[0-4]d 表示 00~49 之間的數

3.三個部分的正則匹配

a) (0~255) 的正規表示式可以寫為 (2((5[0-5])|([0-4]d)))|([0-1]?d{1,2})

b) .(0~255) 的正規表示式可以寫為 .((2((5[0-5])|([0-4]d)))|([0-1]?d{1,2}))

c) .(0~255) 匹配3次的正規表示式可以寫為 (.((2((5[0-5])|([0-4]d)))|([0-1]?d{1,2}))){3}

總結

到此這篇關於正規表示式匹配ip地址的文章就介紹到這了,更多相關正規表示式匹配ip地址內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com