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块)