IPV4和IPV6正則表示式的深入講解
IPV4正則表示式
Ipv4地址分為ABCDE五大類,其中ABC類是普通ip地址,D類是組播地址,E類保留,作為研究之用。
範圍分別為:
A: 1.0.0.1 ―一126.155.255.255
內網地址範圍:10.0.0.0 一一10-255.255.255
B: 127.0.0.1 —191.255.255.255
內網地址範圍:172.16.0.0——172.31.255.255
C: 192.0.0.1 —223.255.255.255
內網地址範圍:192.168.0.0—一192.168.255.255
D: 224.0.0.1 —239.255.255.255
E: 240.0.0.1 —255.255.255.255
我們的正則要求ip必須是ABC類地址。每個位元組的第一個數字可以為0,比如說01,001。
1. ip的第一個位元組分作以下幾種情況:
1.長度為3且以2開頭,範圍為200-223
正則:22[0-3]丨2[0-1][0-9]
2.長度為3且以0或1開頭
正則:[0-1][0-9][0-9]
3.長度為1或2
正則:([0-9])]{1,2}
所以第一個位元組的表示式為:
(22[0-3]丨2[0-1][0-9]|
[0-1][0-9][0-9]|
0[1 -9][0-9]|
([0-9])]{1,2})
2. 後面三個位元組範圍為0-255,前面有一個點
分為以下幾種情況:
1. 以2開頭
正則:25[0-5]|2[0-4][0-9]
2. 以1和0開頭的情況和第一個位元組相同。
所以,單個位元組的正則表示式:
([.]
(25[0-5]|2[0-4][0-9]|
[0-1][0-9][0-9]|
0[1 -9][0-9]|
([0-9])]{1,2}))
3. 加上點號和重複三次,以及開始和結尾匹配符,IPV4最終正則表示式變為:
((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})
點號之所以用中括號括起來是因為如果不擴起來是匹配任意字元。也可以用兩個反斜杆轉義。
加上行首和行尾匹配符:
(^((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})$)
IPV6正則表示式
IPV6介紹
IPV6的長度是128位,相比於ipv4的32位,極大的擴充套件了ip地址可用空間。ipv4地址現在被視為一種稀缺資源,而ipv6地址相當充足,在可以預見的未來是用不完的。有這樣一段描述:如果地球表面(含陸地和水面)都覆蓋著計算機,那麼IPv6允許每平方米擁有7*10A23個IP地址;如果地址分配的速率是每微秒100萬個,那麼需要10A19年才能將所有的地址分配完畢。
IPv6地址表示
IPv6的128位地址通常寫成8組,每組為四個十六進位制數的形式。比如:
AD80:0000:0000:0000:ABAA:0000:00C2:0002
是一個合法的IPv6地址。這個地址比較長,看起來不方便也不易於書寫。零壓縮法可以用來縮減其長度。如果幾個連續段位的值都是0,那麼這些0就可以簡單的以::來表示,上述地址就可寫成:
AD80::ABAA:0000:00C2:0002
這個簡化只能用一次,在上例中的ABAA後面的0000就不能再次簡化。當然也可以在ABAA後面使用::,這樣的話前面的12個0就不能壓縮了。這個限制的目的是為了能準確還原被壓縮的0,不然就無法確定每個::代表了多少個0。例如,下面是一些合法的IPv6地址:
CDCD:910A:2222:5498:8475:1111:3900:2020
1030::C9B4:FF12:48AA:1A2B
2000:0:0:0:0:0:0:1::
0:0:0:0:0:0:12000:0:0:0:0::
同時每個段前面的零可以省略,因此
2001:0DB8:02de::0e13 等價於
2001:DB8:2de::e13
一個IPv6地址可以將一全IPv4地址內嵌進去,寫成IPv6形式和平常習慣的IPv4形式的混合體。
IPv6有兩種內嵌IPv4的方式:IPv4映像地址和IPv4相容地址(已經被捨棄)。
IPv4映像地址
0000:0000:0000:0000:0000:ffff:192.168.89.9這種混合寫法對應的ipv6地址:
0000:0000:0000:0000:0000:ffff:c0a8:5909
其實表示的是192.168.89.9這個ipv4地址。IPv4映像地址佈局如下:
0000…..0000(80bits)| FFFF | IPv4 address |
IPv4相容地址
相容地址和映像地址的區別就是第81-96位為0。
IPv4相容地址佈局如下:
0000…..0000(80bits) | 0000 | IPv4 address |
格式分為以下幾種情況:
1. 前面7個完整的欄位,第8個欄位為零壓縮寫法或者數字。如:
1:2:3:4:5:6:7:8
1:2:3:4:5:6:7::
對應的正則表示式為:
(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}{1}|:))
最外面加一層括號是為了保證與其他正則表示式拼接到一起時保證不產生混亂。
2. 前面6個完整的欄位,後面2個欄位可能為零壓縮寫法或者ipv4地址嵌入式寫法。如:
1:2:3:4:5:6::8
1:2:3:4:5:6::
1:2:3:4:5:6:192.168.1.1
對應的正則表示式為:
(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}{1}|((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})|:))
3. 前面5個完整的欄位,後面3個欄位可能為零壓縮寫法或者ipv4地址嵌入式寫法。如:
1:2:3:4:5::
1:2:3:4:5::6
1:2:3:4:5::8
1:2:3:4:5::192.168.1.1
對應的正則表示式為:
(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}{1,2}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})|:))
4. 前面4個完整的欄位,後面4個欄位可能為零壓縮寫法或者ipv4地址嵌入式寫法。如:
1:2:3:4::
1:2:3:4::5
1:2:3:4::8
1:2:3:4::192.168.1.1
對應的正則表示式為:
(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,3}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})|:))
前面3,2,1個完整欄位的情況略。
8. 第一個欄位即開始簡略寫法
::8
::192.168.1.1
對應的正則表示式為:
(:(:[0-9A-Fa-f]{1,7}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})|:))
所以IPV6的正則表示式為:
(([0-9A-Fa-f]{1,4}{1}|:))|
(([0-9A-Fa-f]{1,2})){3})|:))|
(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,4}:){2}(:[0-9A-Fa-f]{1,5}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,4}:){1}(:[0-9A-Fa-f]{1,6}|:((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})|:))|
(:(:[0-9A-Fa-f]{1,2})){3})|:))
上面為了表達邏輯的清晰,用了換行符,刪除換行符,便得到IPV6的最終正則表示式:
(([0-9A-Fa-f]{1,4}{1}|:))|(([0-9A-Fa-f]{1,2})){3})|:))|(([0-9A-Fa-f]{1,2})){3})|:))|(:(:[0-9A-Fa-f]{1,2})){3})|:))
加上行首和行尾匹配符:
(^(([0-9A-Fa-f]{1,2})){3})|:))$)
上面的表示式還有考慮的不完善的地方:相容地址和對映地址的前80bit一定是0,所以上面的範圍其實寫的更寬了,而且使表示式變複雜了。但是發現這個問題的時候,已經沒有優化的需求了,所以就先這樣,有需要的自行進行優化。
HTTPS
正則:
((http|https|HTTP|HTTPS)://.{1,245})
加上行首和行尾匹配符:
(^((http|https|HTTP|HTTPS)://.{1,245})$)
域名
對應的規則:
1. 非最後一段
a. 字元範圍為:a-zA-Z0-9以及短劃線-
b. 開始和結束字元不能為-
c. 長度不超過63
2. 最後一段
a. 字元範圍為a-zA-Z
b. 長度為2-6
3. 不能只有最後一段
正則:
(([a-zA-Z0-9](([a-zA-Z0-9]|[-]){0-61}[a-zA-Z0-9])?[.])+[a-zA-Z0-9]{2,6}
加上行首和行尾匹配符:
(^(([a-zA-Z0-9](([a-zA-Z0-9]|[-]){0-61}[a-zA-Z0-9])?[.])+[a-zA-Z0-9]{2,6}$)
空字串
(^$)
附IPv4及IPv6正則測試用例——java:
import org.junit.Test; public class IPv6Test { public static final String ipv4Regex = "(^((22[0-3]丨2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})$)"; public static final String ipv6Regex = "(^(([0-9A-Fa-f]{1,2})){3})|:))$)"; public static final String httpRegex = "(^((http|https|HTTP|HTTPS)://.{1,245})$)"; public static final String domainRegex = "(^(([a-zA-Z0-9](([a-zA-Z0-9]|[-]){0-61}[a-zA-Z0-9])?[.])+[a-zA-Z0-9]{2,6}$)"; public static final String emptyRegex = "(^$)"; public static final String finalRegex = ipv4Regex + "|" + ipv6Regex + "|" + httpRegex + "|" + domainRegex + "|" + emptyRegex; public static void main(String args[]) { try { } catch (Exception e) { e.printStackTrace(System.out); } } // 第一個欄位長度為3的測試用例 @Test public void testIpv4_1() { assert ("200.255.255.255".matches(finalRegex)); assert ("223.255.255.255".matches(finalRegex)); assert ("224.255.255.255".matches(finalRegex)); assert ("192.0.0.1".matches(finalRegex)); assert ("127.0.0.1".matches(finalRegex)); assert ("100.0.0.1".matches(finalRegex)); assert ("090.0.0.1".matches(finalRegex)); assert ("009.0.0.1".matches(finalRegex)); } // 第一個欄位長度為1或2的測試用例 @Test public void testIpv4_2() { assert ("09.255.255.255".matches(finalRegex)); assert ("90.255.255.255".matches(finalRegex)); assert ("00.255.255.255".matches(finalRegex)); assert (!"-.0.0.1".matches(finalRegex)); assert ("0.0.0.1".matches(finalRegex)); assert ("1.0.0.1".matches(finalRegex)); } // 測試後面三個位元組 @Test public void testIpv4_3() { assert ("200.0.255.255".matches(finalRegex)); assert ("200.01.255.255".matches(finalRegex)); assert ("200.10.255.255".matches(finalRegex)); assert (!"200.256.255.255".matches(finalRegex)); assert ("200.001.255.255".matches(finalRegex)); assert ("200.255.0.255".matches(finalRegex)); assert ("200.255.01.255".matches(finalRegex)); assert ("200.255.10.255".matches(finalRegex)); assert (!"200.255.256.255".matches(finalRegex)); assert ("200.255.001.255".matches(finalRegex)); assert ("200.255.255.0".matches(finalRegex)); assert ("200.255.255.01".matches(finalRegex)); assert ("200.255.255.10".matches(finalRegex)); assert (!"200.255.255.256".matches(finalRegex)); assert ("200.255.255.001".matches(finalRegex)); } // 測試異常 @Test public void testIpv4_4() { assert (!"200".matches(finalRegex)); assert (!"200.1".matches(finalRegex)); assert (!"200.1".matches(finalRegex)); assert (!"200.1.1".matches(finalRegex)); assert (!"200.1.1.1.1".matches(finalRegex)); } @Test public void testIpv6_1() { assert ("1:2:3:4:5:6:7::".matches(finalRegex)); assert ("1:2:3:4:5:6:7:8".matches(finalRegex)); assert ("1:2:3:4:5:6::".matches(finalRegex)); assert ("1:2:3:4:5:6::8".matches(finalRegex)); assert ("1:2:3:4:5::".matches(finalRegex)); assert ("1:2:3:4:5::8".matches(finalRegex)); assert ("1:2:3:4::".matches(finalRegex)); assert ("1:2:3:4::8".matches(finalRegex)); assert ("1:2:3::".matches(finalRegex)); assert ("1:2:3::8".matches(finalRegex)); assert ("1:2::".matches(finalRegex)); assert ("1:2::8".matches(finalRegex)); assert ("1::".matches(finalRegex)); assert ("1::8".matches(finalRegex)); assert ("::".matches(finalRegex)); assert ("::8".matches(finalRegex)); assert ("::7:8".matches(finalRegex)); assert ("::6:7:8".matches(finalRegex)); assert ("::5:6:7:8".matches(finalRegex)); assert ("::4:5:6:7:8".matches(finalRegex)); assert ("::3:4:5:6:7:8".matches(finalRegex)); assert ("::2:3:4:5:6:7:8".matches(finalRegex)); assert ("::192.168.1.1".matches(finalRegex)); } @Test public void testIpv6_2() { assert ("A:0f:0F:FFFF:5:6:7:8".matches(finalRegex)); assert (!"A:0f:0F:FFFF1:5:6:7:8".matches(finalRegex)); assert (!"G:0f:0F:FFFF:5:6:7:8".matches(finalRegex)); } @Test public void testHttp() { assert ("https://a.com".matches(finalRegex)); assert ("https://a.b.c.com".matches(finalRegex)); assert ("https://a".matches(finalRegex)); assert ("https://a.comdddd".matches(finalRegex)); assert (!"https://afadfadfadfadfadfadfadfadfadfffffffffffffffffffffffffffffffffffffffffffffffdfadfadfadfadfadfadfadfaafadfadfadfadfadfadfadfadfadfffffffffffffffffffffffffffffffffffffffffffffffdfadfadfadfadfadfadfadfaafadfadfadfadfadfadfadfadfadfffffffffffffffffffffffffffffffffffffffffffffffdfadfadfadfadfadfadfadfa.comdddd" .matches(finalRegex)); } @Test public void testDomain() { assert ("a.com".matches(finalRegex)); assert ("a.bdfad-dfadf.c.com".matches(finalRegex)); assert (!"a.-bdfad-dfadf.c.com".matches(finalRegex)); assert ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijk.com".matches(finalRegex)); assert (!"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijk1.com".matches(finalRegex)); } @Test public void testEmpty() { assert ("".matches(finalRegex)); assert (!"1".matches(finalRegex)); } }
到此這篇關於IPV4和IPV6正則表示式的文章就介紹到這了,更多相關IPV4和IPV6正則表示式內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!