這里給大家詳細講解一下一個匹配IP地址的正則表達式,
有關正則方面的知識,會在詳細的講解中提到。
在講解之前,我先給大家介紹一下,ip地址的生成規(guī)則。
IP地址,是由32位數字二進制轉為四個十進制的字符串組成。
怎么轉化?下面講解:
二進制:11111111111111111111111111111111
分為四部分:11111111.11111111.11111111.11111111
轉化:2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0=255
轉為十進制范圍:0~255.0~255.0~255.0~255
這就是IP地址的范圍。
根據這個生成IP的規(guī)則和范圍,我們可以用正則表達式來匹配出IP地址,但怎么匹配呢?各人有各人的方法,這里我講解一下我的思路。
根據IP地址的字符串規(guī)律,我把匹配IP地址的表達式分為兩部分來考慮。
第一部分:匹配3個0~255.(注意后面的一個點)
第二部分:匹配最后的數字0~255
也就是說,先匹配出 0~255.(注意后面的一個點) 這個字符串,然后重復匹配3次,然后再匹配最后的數字部分0~255。這就是我匹配IP地址的思路。
首先,我要提一下,正則是沒有辦法做數字運算的,所以,我們無法用數字運算的方式篩選出IP的數字范圍。既然沒法用數字運算的方式篩選出IP的數字范圍,那么我們應該用什么其他方式來篩選這個數字范圍呢?我的思路是分組討論,然后再把這些分組合并起來組成IP的數字范圍。
①、假設IP的數字是百位數,那么根據IP的數字范圍,我們可以得出下面幾種情況。假設第一個數字為1,那么這個數字的范圍就為1[0-9][0-9]。這個應該不難理解,就不解釋。
②、假設第一個數字為2,那么根據IP數字的范圍規(guī)則,這里又要分為兩種情況,為什么?你想想,最大數字是255,當十位數為5時,個位數最大只能為5是吧?而當十位數為0到4時,個位數可以是任意數字對吧?
所以,這里的兩種情況分別為:
A、2[0-4][0-9]
B、25[0-5]
③、分析完了百位數的情況,接下來就是十位數的情況了,假如是十位數,那么十位數的前面第一個數不能為零是吧?
所以十位數的情況可以是:[1-9][0-9]
④、剩下的就是個位數的情況了,個位數的情況,大家應該很容易得出結論,就是:[0-9]。
四種情況分析下來,我們得出了IP數字的范圍分組為:
1[0-9][0-9]
2[0-4][0-9]
25[0-5]
[1-9][0-9]
[0-9]
怎么把上面的分組用正則表達式表示出來呢?很簡單,用正則的或符號|和分組符號()就可以了,所以上面的分組正則表達式為:
1
|
(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]) |
寫到這里,數字的匹配范圍正則表達式已經寫好了,那么根據我前面的思路: 第一部分:匹配3個0~255.(注意后面的一個點)
第二部分:匹配最后的數字0~255
我們來匹配IP地址的第一部分,正則表達式如下:
1
|
(1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.) |
我在每個數字的后面加了一個點就是匹配出0~255.(注意后面的一個點)
那么怎么重復匹配三次呢?很簡單,我們只要把這五個分組當成整體,再重復匹配三次就行了,正則表達式如下:
1
|
((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9])\.)){3} |
第一部分已經匹配出來了,接下來就是拼接上第二部分的數字了,數字部分上面已經寫得很清楚了,就不再解釋了,下面是完整的正則表達式:
1
|
((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9])) |
寫到這里,正則匹配IP的表達式已經出來了,不過,這并不是最終的匹配IP的正則表達式,為什么呢?很簡單,正則表達式會對每一個分組都進行捕獲匹配,上面把匹配IP分成了那么多分組,而每一個分組的內容都會被正則所捕獲,那上面不知道已經捕獲多少IP了,呵呵,那么怎么去掉分組的內容呢?很簡單,用這個符號?:
?:符號放在()圓括號里面,是捕獲分組,但不捕獲正則表達式的內容的意思。那么,我們把它放到每一個分組里面去,不就去掉了分組的內容了嗎?所以,我們還要給每個分組加上?:,加上后正則如下:
1
|
(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9])) |
即使到這里,還是沒有把IP地址匹配出來,我們還要用^和$來限制字符串的開頭和結尾,所以,最后的匹配IP地址的正則表達式是:
1
|
^(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$ |
這就是我匹配IP地址最完整的正則表達式,大家可以借鑒一下,有什么bug還望讀者提出,免得誤導其他讀者。
上面的正則表達式的()括號都是成對出現的,假如有不成對出現,請讀者自己添加一下,可能是我漏寫了。
下面是我的測試:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
<?php $pattern = '/^(?:(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:1[0-9][0-9]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:2[0-5][0-5])|(?:25[0-5])|(?:1[0-9][0-9])|(?:[1-9][0-9])|(?:[0-9]))$/' ; //正則匹配ip地址 $ip = '254.21.0.198' ; preg_match( $pattern , $ip , $out ); echo '<pre>' ; print_r( $out ); $ip = '255.777.0.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '07.25.8.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '1207.25.8.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = 'qq107.25.8.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '\.\.\.107.25.8.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '\.\.\. 7.25.8.198' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '107.25.8.19822vvv' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '107.25.r8.1982' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '107.225.8.19' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '225.225.225.225' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '0.0.0.0' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '00.0.0.0' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '0.202.1.0' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '0.202.1.226' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $ip = '249.202.1.0' ; preg_match( $pattern , $ip , $out ); print_r( $out ); $s = '' ; for ( $i =0; $i <32; $i ++){ $s .= '1' ; } echo $s ; echo strlen ( $s ); |
原文鏈接:http://www.cnblogs.com/loveyoume/archive/2016/12/25/6220275.html