一、正则匹配基本知识及概念

在练习之前,需要大家知道一些基本知识,如果有一定基础的可以跳过该步骤,直接往下看。

正则表达式-字符类

[abc]:代表a或者b,或者c字符中的一个。
[^abc]:代表除a,b,c以外的任何字符。
[a-z]:代表a-z的所有小写字符中的一个。
[A-Z]:代表A-Z的所有大写字符中的一个。
[0-9]:代表0-9之间的某一个数字字符。
[a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
[a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符。

正则表达式-逻辑运算符

&&:并且
| :或者(可以省略)

正则表达式-预定义字符

“.” : 匹配任何字符。
“\d”:任何数字[0-9]的简写;
“\D”:任何非数字[^0-9]的简写;
“\s”: 空白字符:[ \t\n\x0B\f\r] 的简写
“\S”: 非空白字符:[^\s] 的简写
“\w”:单词字符:[a-zA-Z_0-9]的简写
“\W”:非单词字符:[^\w]

正则表达式-数量词

x? : 0次或1次
x* : 0次到多次
x+ : 1次或多次
X{n} : 恰好n次
X{n,} : 至少n次
X{n,m}: n到m次(n和m都是包含的,最少n次,最多m次。

二、ip地址匹配

题目要求:使用正则表达式匹配192.11.23.69

须知:ip地址的范围为0.0.0.0-255.255.255.255

接下来我们直接进入正题吧!在我们看到题目的第一眼,大家可能觉得很简单,这不就用\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

zh

这里我们可以看到使用上述表达式的确匹配成功。

虽然完成了我们的题目要求,有些细心的伙伴会发现,用红色标注出来的部分,重复了三遍,是不是我们可以用分组的方式来简化表达式并完成题目要求。我们把上面的匹配表达式换成分组之后的样子,即(\d{1,3}\.){3}\d{1,3}

表达式讲解:(\d{1,3}\.) 匹配我们前三段的ip地址和’.‘,因为第四段ip地址最后面不能有’.',如果我们使用在同一个分组去匹配就会出现错误情况,而\d{1,3}刚好匹配我们最后一段ip地址

匹配效果如下:

匹配同样成功,该模式有什么不对的地方吗?从语法上看,完全正确,也达到了我们的题目要求,可是我们有没有注意到,我们日常生活中所用的ip地址每一位都是在0-255之间,但是我们上面写的表达式会匹配0-999之间的所有ip地址,如果在未来的工作中,有这样的需求,要匹配所有合法的ip地址,那么我们上面所写的正则表达式是不是就不符合要求了,这里就需要我们使用子表达式的嵌套(注意:有一点很重要。通过上面的例子,我们发现,写一个能够匹配预期内容的正则表达式其实并不难,但是写一个能够考虑到所有可能场景,确保将不需要匹配的内容排除在外的正则表达式就困难多了)

所以我将上面的表达式又改进了一下(这里用到了子表达式的嵌套,如果不懂的小伙伴可以先看一下基本概念再来看接下来的内容)。我们发现当ip地址仅有一位或者两位的时候(即1.1.1.1 or 11.11.11.11),用(\d{1,2}\.)就可以完成匹配,当ip地址为三位的时候,会有这么两种情况(这里留下个疑问,考虑到初学者可能犯错的情况)?
1:ip地址开头为1的时候,我们后面的两位每一位的范围都在0-9之间,而\d这个元字符刚好满足了我们的要求,所以使用(1\d{2}.)就满足了我们在100-199ip地址的匹配,这个其实还相对简单,接下来就是200-255之间ip地址的匹配了,有些同学可能会想,我们可以使用匹配100-199的表达式来实现对200-255ip地址的匹配,即(2\d{2}\.)这样的表达式来实现,可是这样会把256-299之间的ip地址匹配到,违反了我们的意愿,所以我改良了一下表达式(2[0-5]{2}\.]),这样就只会匹配到200-255之间的ip地址,既然子表达式都写好了,就让我们来实践看看效果吧!

表达式为:((1\d{2}.)|(2[0-5]{2}.)|(\d{1,2}.)){3}((\d{1,2})|(1\d{2})|(2[0-5]{2}))),伙伴们可以一起实践一下!

匹配成功,可是再写出这个表达式,我们要测试某些特殊情况是否不在我们的匹配范围内,于是我发现了以下两个比较重要的问题。

第一种:

合法ip地址匹配错误

第二种:

非法ip地址匹配成功

为什么会出现上面的情况?

当我们觉得表达式很完美的时候,虽然256超出匹配范围,但是因为(\d{1,2}\.)的影响,使得我们的非法表达式也匹配成功,本来192.11.23.200为合法表达式,却只匹配到了98.11.23.200,请大家看我用红色箭头标注的地方,会不会跟我们子表达式的顺序有关呢?那好,我来改变一下顺序,我们将(\d{1,2}\.)放到了最后,防止出现错误匹配
改变匹配顺序后的表达式为:

( ( (2[0-5]{2}.)|(1\d{2}.)|(\d{1,2}.)){3}((1\d{2})|(2[0-5]{2})|(\d{1,2})))

果然,第一种情况我们是因为子表达式顺序的原因,导致匹配错误。

可是第二种情况使用改变顺序的表达式,依然会出现以上问题(这里也就印证了上文提到的那些话,要想写出一个符合规范的表达式就很困难)。

于是这里的^就起到了作用,我们可以把第一个子表达式单另拉出来加上^表示第一段ip地址开头为(\d{1,2}),这样刚好避免了我们如上的情况,效果如下:

可以看到非法ip不在我们的匹配当中。

其实写到这里大家是不是感觉已经大功告成了?回答:No

(2[0-5]{2})这个表达式能否匹配239这个ip呢?不知道有没有细心的小伙伴发现

所以最终正确的表达式应该为:

(^((2[0-4]\d.)|(25[0-5].)|(1\d{2}.)|(\d{1,2}.))((2[0-5]{2}.)|(1\d{2}.)|(\d{1,2}.){2})((1\d{2})|(2[0-5]{2})|(\d{1,2})))

在这里可以跟大家说一下,是否可以使用$来避免我们上述第一种问题,有兴趣的可以尝试一下,到这里,我们这道题目也算基本符合规范的完成了

总结

到此这篇关于正则表达式匹配ip地址的文章就介绍到这了,更多相关正则表达式匹配ip地址内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部