首頁  >  文章  >  後端開發  >  正規表示式符合IP的表達式(推薦)

正規表示式符合IP的表達式(推薦)

高洛峰
高洛峰原創
2017-01-09 16:35:303389瀏覽

這裡給大家詳細講解一下一個符合IP位址的正規表示式,

  有關正規方面的知識,會在詳細的講解中提到。

  在講解之前,我先跟大家介紹一下,ip位址的產生規則。

  IP位址,是由32位元數字二進位轉為四個十進位的字串組成。

  怎麼轉化?下面說明:

      二進位:111111111111111111111111111111111

    

      轉換: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的規則和範圍,我們可以用正規表示式來配對出IP位址,但要怎麼符合呢?各人有各人的方法,這裡我講解一下我的思路。

      根據IP位址的字串規律,我把符合IP位址的表達式分成兩個部分來考慮。

      第一部分:配對3個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]

    ③、分析完了百位數的情況,接下來就是十位數的情況了,假如是十位數,那麼十位數的前面第一個數不能為零是吧?

所以十位數的情況可以是:[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

     

(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 = &#39;/^(?:(?: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]))$/&#39;;
//正则匹配ip地址
$ip     = &#39;254.21.0.198&#39;;
preg_match($pattern,$ip,$out);
echo &#39;<pre class="brush:php;toolbar:false">&#39;;
print_r($out);
$ip     = &#39;255.777.0.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;07.25.8.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;1207.25.8.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;qq107.25.8.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;\.\.\.107.25.8.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;\.\.\.  7.25.8.198&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;107.25.8.19822vvv&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;107.25.r8.1982&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;107.225.8.19&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;225.225.225.225&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;0.0.0.0&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;00.0.0.0&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;0.202.1.0&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;0.202.1.226&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$ip     = &#39;249.202.1.0&#39;;
preg_match($pattern,$ip,$out);
print_r($out);
$s=&#39;&#39;;
for($i=0;$i<32;$i++){
  $s .= &#39;1&#39;;
}
echo $s;
echo strlen($s);

更多正则表达式匹配IP的表达式(推荐)相关文章请关注PHP中文网!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn