ここではIPアドレスにマッチする正規表現について詳しく解説します
正規表現についての知識は詳しい解説の中で触れます。
説明する前に、まずはIPアドレス生成のルールをご紹介します。
IPアドレスは、32桁の2進数を4つの10進数の文字列に変換したものです。
変換するにはどうすればいいですか?以下で説明します:
バイナリ: 11111111111111111111111111111
4 つの部分に分割: 11111111.11111111.11111111.11111111
変換: 2^7+2^6+2^5+2^ 4+2^3+2^2+2^1+ 2^0=255
10進数に変換: 0~255.0~255.0~255.0~255
IPアドレスの範囲です。
IP生成のルールと範囲に基づいて、正規表現を使用してIPアドレスを照合できますが、どのように照合するのでしょうか?人それぞれ独自の方法があると思いますが、ここでは私のアプローチを説明します。
IP アドレスの文字列規則に基づいて、IP アドレスに一致する式を 2 つの部分に分けて検討しました。
use using この文字列をクリックして、一致を 3 回繰り返し、最後の数字の部分 0 ~ 255 を一致させます。これが私の考えたIPアドレスの一致です。
まず最初に、正規表現で数値演算を行う方法がないため、数値演算を使用して IP の数値範囲をフィルタリングすることはできないことを述べておきたいと思います。数値演算を使用して IP の数値範囲をフィルタリングする方法がないため、この数値範囲をフィルタリングするには他にどのような方法を使用すればよいでしょうか?私のアイデアは、グループで話し合い、それらのグループを統合して IP の数値範囲を形成することです。
① IP の数が数百であると仮定すると、IP 番号の範囲に基づいて、次のような状況を描くことができます。最初の数値が 1 であると仮定すると、この数値の範囲は 1[0-9][0-9] になります。これを理解するのは難しくないと思いますので、説明は省略します。
②. 最初の数値が 2 だとすると、IP 番号の範囲規則に従って、ここには 2 つの状況が存在します。考えてみてください。最大の数は 255 です。十の位が 5 のとき、一の位は最大でも 5 までですよね。そして十の位が0~4の場合、一の位はどんな数字でもいいですよね?したがって、ここでの 2 つの状況は次のとおりです:
A, 2 [0-4] [0-9]
B, 25 [0-5] ③ ③、100 桁の状況を分析し、それを取得します 次はケースです10の位の場合、10の位の前の最初の数字はゼロにはなりませんよね?
したがって、10 桁の状況は次のようになります: [1-9][0-9]
④. 残りは 1 桁の状況です。 : [0-9]。 cone 4つの状況を分析した後、IP番号の範囲グループ化を次のように思いつきました。1[0-9] [0-9] 2 [0-4] [0-9]
-5] [1-9][0-9] [0-9] [0-9] [0-9] 死ぬ非常に単純です。通常の or シンボル | とパケット シンボル () を使用するだけです。したがって、上記の正規表現は次のようになります。最後のドット)(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9])。非常に簡単です。これら 5 つのグループを全体として扱い、マッチングを 3 回繰り返すだけです。
(1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)最初の部分は一致しました。次のステップは、2 番目の数字を結合することです。数字の上の部分 非常にわかりやすく書かれているので、これ以上は説明しません。完全な正規表現は次のとおりです。
((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 class="brush:php;toolbar:false">'; 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);
更多正则表达式匹配IP的表达式(推荐)相关文章请关注PHP中文网!