這裏給你們詳細講解一下一個匹配IP地址的正則表達式,php
有關正則方面的知識,會在詳細的講解中提到。正則表達式
在講解以前,我先給你們介紹一下,ip地址的生成規則。測試
IP地址,是由32位數字二進制轉爲四個十進制的字符串組成。spa
怎麼轉化?下面講解:code
二進制:11111111111111111111111111111111blog
分爲四部分:11111111.11111111.11111111.11111111ip
轉化:2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0=255字符串
轉爲十進制範圍:0~255.0~255.0~255.0~255class
這就是IP地址的範圍。bug
根據這個生成IP的規則和範圍,咱們能夠用正則表達式來匹配出IP地址,但怎麼匹配呢?各人有各人的方法,這裏我講解一下個人思路。
根據IP地址的字符串規律,我把匹配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數字的範圍規則,這裏又要分爲兩種狀況,爲何?你想一想,最大數字是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[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[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)
我在每一個數字的後面加了一個點就是匹配出0~255.(注意後面的一個點)
那麼怎麼重複匹配三次呢?很簡單,咱們只要把這五個分組當成總體,再重複匹配三次就好了,正則表達式以下:
((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]\.)){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[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[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還望讀者提出,省得誤導其餘讀者。
上面的正則表達式的()括號都是成對出現的,假若有不成對出現,請讀者本身添加一下,多是我漏寫了。
下面是個人測試:
<?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);