JAVA正則表示式區分IPv4和IPv6地址
PS*程式碼直接見第二部分:
一、進入正題前先說說JAVA正則表示式相關概念:
1、常用字元類:
[abc] == a||b||c [a-zA-Z] == 所有大小寫字母中的任意一個 [0-9A-Za-z] == 任意一個字母或者數字
。。。。。。懶得打字了,直接上截圖(Think in Java)
2、常用邏輯操作符、邊界匹配符
3、量詞(常用)
4、常用表示式以及意義:
? 示例:(X)? 0個或1個X
+ 示例:(X)+ 1個或多個X
* 示例:(X)* 0個或多個X
5、Pattern和Matcher類
這兩個類上手使用比較簡單,學習JAVA正則表示式建議仔細讀一讀
PS* 一定請注意 '?:' 非獲取匹配,匹配冒號後的內容但不獲取匹配結果,不進行儲存供以後使用,在不想被捕獲的時候使用 可以提高程式執行速度
比如有正則表示式,正則表示式開頭出現的 '?:' 你可以把它理解成一個開關,寫上它將不進行儲存,可以提高執行速度,但是不能反向引用了;如果你只是想要匹配這個功能是可以大膽的寫在開頭的;但是如果你想要使用一些其它的中間結果,那麼就不能使用這個開關了。
Pattern regexs = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
二、JAVA正則表示式區分IPv4和IPv6地址
輸入資料合法格式:
IPv4:唯一標準格式 -> 0-255.0-255.0-255.0-255
IPv6: 標 準 格 式 -> abcd:abcd:abcd:abcd:abcd:abcd:abcd:abcd
IPv6 壓 縮 格 式 -> abcd::abcd:abcd:abcd:abcd
::abcd:abcd:abcd
abcd:abcd:abcd:abcd:abcd::
::1
::
IPv6壓縮規則:必需至少兩個全0塊才可以壓縮,且每個IPv6地址只能壓縮一次,存在多個可以壓縮的位置優先壓縮左邊的全0塊
import java.util.regex.Pattern;
public class JudgeIpAddress {
//功能:判斷IPv4地址的正則表示式:
private static final Pattern IPV4_REGEX =
Pattern.compile(
"^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
//功能:判斷標準IPv6地址的正則表示式
private static final Pattern IPV6_STD_REGEX =
Pattern.compile(
"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
//功能:判斷一般情況壓縮的IPv6正則表示式
private static final Pattern IPV6_COMPRESS_REGEX =
Pattern.compile(
"^((?:[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((?:([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$");
/*由於IPv6壓縮規則是必須要大於等於2個全0塊才能壓縮
不合法壓縮 : fe80:0000:8030:49ec:1fc6:57fa:ab52:fe69
-> fe80::8030:49ec:1fc6:57fa:ab52:fe69
該不合法壓縮地址直接壓縮了處於第二個塊的單獨的一個全0塊,
上述不合法地址不能通過一般情況的壓縮正則表示式IPV6_COMPRESS_REGEX判斷出其不合法
所以定義瞭如下專用於判斷邊界特殊壓縮的正則表示式
(邊界特殊壓縮:開頭或末尾為兩個全0塊,該壓縮由於處於邊界,且只壓縮了2個全0塊,不會導致':'數量變少)*/
//功能:抽取特殊的邊界壓縮情況
private static final Pattern IPV6_COMPRESS_REGEX_BORDER =
Pattern.compile(
"^(::(?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5})|((?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5}::)$");
//判斷是否為合法IPv4地址
public static boolean isIPv4Address(final String input){
return IPV4_REGEX.matcher(input).matches();
}
//判斷是否為合法IPv6地址
public static boolean isIPv6Address(final String input) {
int NUM = 0;
for(int i = 0;i<input.length();i++){
if(input.charAt(i) == ':')NUM++;
}
if(NUM > 7) return false;
if(IPV6_STD_REGEX.matcher(input).matches()){
return true;
}
if(NUM == 7){
return IPV6_COMPRESS_REGEX_BORDER.matcher(input).matches();
}
else{
return IPV6_COMPRESS_REGEX.matcher(input).matches();
}
}
public static void main(String args[])
{
String ipAddr = "A00:a00:100:f261::F15";
//fe80:1295:8030:49ec:1fc6:57fa:0000:0000
//A00:a00:100::f261:F15
//fe80:1295:8030:49ec:1fc6:57fa::
System.out.println(ipAddr);
if(isIPv6Address(ipAddr)){
System.out.println("IPV6地址");
}
else if(isIPv4Address(ipAddr)){
System.out.println("IPV4地址");
}
else{
System.out.println("不合法地址");
}
}
}
之前看過一個同行類似的帖子,但是那個同行關於處理,壓縮的IPv6地址,的正則表示式有一個缺陷:當一個IPv6地址為壓縮格式的時候,其正則表示式不能除掉哪些長度超過6塊的不合法的IPv6地址(由IPv6最少壓縮兩個全0塊的壓縮規則可知,一個被壓縮的IPv6地址最多有6塊)