在今天写后端的时候因为要在后端对前端传输过来的ip地址内容进行验证,所以就有了这篇文章
首先ipv4的ip地址的写法规则为 xxx.xxx.xxx.xxx
且每一个xxx的范围为 0-255
((2(5[0-5]|[0-4]\d))|((1\d{2})|[1-9]\d|[0-9]))(\.((2(5[0-5]|[0-4]\d))|((1\d{1,2})|[1-9]\d|[0-9]))){3}
优化后用于判断一个ip地址字符串是否满足规则 可直接跳转到 “再优化”板块查看函数
下方为通过java实现对输入的ip地址的验证:
函数返回值:
0:ip地址不符合它的规则
1:符合ip地址规则
下面这个函数是自己想的时候写的,功能虽然能实现 但是过程还是比较粗糙,没那么精致
private int judgeIP(String ip){
String[] result = ip.split("\\.");
//ip地址由"."分为四段
int standardLen = 4;
if(result.length != standardLen){
return 0;
}
else{
//能由"."分为四段
for (String temp:result) {
//遍历判断
/*判断是否为非0开头的 整数*/
if(temp.matches("0|[1-9][0-9]*")){
int tempInt = Integer.valueOf(temp);
if(tempInt > 255||tempInt <0){
//是数字 但是取值范围不对 0 -255
return 0;
}
//符合规范就继续验证下一个 直到四个都验证完
}
else{
//不是数字的 或者字符串0开头的 正则匹配失败
return 0;
}
}
//遍历完所有ip 完全符合规范的
return 1;
}
}
大致过程是将输入的ip地址字符串根据 "."分为四段 先将不符合这一基本规则的字符串给筛选出去,然后判断每一段是否在0-255的范围内 这儿使用了正则表达式
所使用到的正则为:0|[1-9][0-9]*
其表达的含义为:0 和 非0开头的正整数 [0-9]*表示前面是1-9开头的数字 后面的数字0-9
所以[1-9][0-9]*
所表示的数的范围为:1-无限大 至于到255的范围 后面单独判断
这儿不包含0
所以0
要单独写
因为ip是0-255 故可以完全将ip地址的匹配交给正则表达式:
((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}
该正则表达式来自 菜鸟正则表达式在线测试的页尾
首先上面这个正则表达式可以拆分为两个部分:
((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})
和
(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}
两个部分
第一部分:((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})
:该段为匹配xxx.xxx.xxx.xxx 的第一段红色部分(不含 “.” )
在 “|” 将它们分开 然后左右分别表示
(2(5[0-5]|[0-4]\d)) : 200-255
[0-1]?\d{1,2}:0-199
总的范围表示为:0-255
第二部分: (\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}
为了匹配xxx.xxx.xxx.xxx 后面三个部分(包含 ‘.’ )
这部分和前面的有些相似 在{ }里面作用是用于控制前面匹配的次数
测试记录:
上图为用上面的正则表达式对输入的一些ip案例进行了验证 能够匹配去除掉大部分错误案例
数字不在0-255的范围内的,不符合ip地址规范(四位0-255组成,且由
进行分开)
但是仍有一部分问题 那就是像匹配到的第一个和第4个这种0开头的给去除(但这个位置可能为0 不能去除0这个单独的数字 但也不能是由0开头的一个数字(不符合整数的组成规则))
优化结果:
((2(5[0-5]|[0-4]\d))|((1\d{2})|[1-9]\d|[0-9]))(\.((2(5[0-5]|[0-4]\d))|((1\d{1,2})|[1-9]\d|[0-9]))){3}
该正则表达式能够去除中间为0 的情况,相比上一个版本更加的准确
在idea中创建了一个application 然后去运行这个函数
修改后的方法 最终版(判断是否满足规则(能否有匹配值) 或 (代码中注释内容)遍历匹配到的内容)private static String judgeIP2(String ip){
String zz_rules = "((2(5[0-5]|[0-4]\\d))|((1\\d{2})|[1-9]\\d|[0-9]))(\\.((2(5[0-5]|[0-4]\\d))|((1\\d{1,2})|[1-9]\\d|[0-9]))){3}";
/* 该段注释 遍历匹配到的所有值 结果
Pattern p = Pattern.compile(zz_rules);
List result = new ArrayList<>();
Matcher m = p.matcher(ip);//进行匹配
while (m.find()) {//判断正则表达式是否匹配到
String part = m.group();//通过group来获取每个分组的值,group(0)代表正则表达式匹配到的所有内容,1代表第一个分组
result.add(part);
System.out.println(result);
}
*/
//"字符串".matches(String) 的返回值是一个boolean 值 只能作为判断是否有匹配的字段
if(ip.matches(zz_rules)){
return "匹配到了结果";
}
else {
return "无匹配字段";
}
// return "测试";
}
在改写正则表达式的过程中发现一个匹配过程中存在的贪婪问题:单独开一篇文章来说明这个问题
菜鸟正则表达式语法:https://www.runoob.com/regexp/regexp-syntax.html
菜鸟工具:https://c.runoob.com/front-end/854/