亲宝软件园·资讯

展开

正则表达式匹配ip地址超详细讲解

m0_65463546 人气:0

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

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

正则表达式-字符类

[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地址小结

1. IP段都表示一个字节,即只能在 0~255之间。

所以一个正确的IP应该是:(0~255) .(0~255) .(0~255) .(0~255)

通过观察可以发现可以将整个IP分为两部分匹配,即:(0~255) 和 .(0~255) 3次

2. 0~255可以分两部分匹配 0~199 和 200~255

a) 0~199 正则表达式为 [0-1]?\d{1,2}

[0-1]? 表示匹配 0或1一次或零次

\d 表示匹配任意一个十进制数字,即 0~9

{1,2} 表示匹配上一个元素至少一次,最多两次,这里就是 \d一次或两次

b) 200~255 正则表达式为 2((5[0-5])|([0-4]\d)),又可以分为两部分 200~249 和 250~255

2 表示必须以2开头

5[0-5] 表示匹配 50~55 之间的数

[0-4]\d 表示 00~49 之间的数

3.三个部分的正则匹配

a) (0~255) 的正则表达式可以写为 (2((5[0-5])|([0-4]\d)))|([0-1]?\d{1,2})

b) .(0~255) 的正则表达式可以写为 .((2((5[0-5])|([0-4]\d)))|([0-1]?\d{1,2}))

c) .(0~255) 匹配3次的正则表达式可以写为 (.((2((5[0-5])|([0-4]\d)))|([0-1]?\d{1,2}))){3}

总结

加载全部内容

相关教程
猜你喜欢
用户评论