起初,我认为在互联网上很容易找到只匹配公共IPv4地址的正则表达式。然而,经过大量的谷歌搜索后,我一无所获,所以我尝试编写正则表达式,如下(Perl 风格),
[0-9]\.(?:[0-9]{1,3}\.){2}[0-9]{1,3}|
1[1-9]\.(?:[0-9]{1,3}\.){2}[0-9]{1,3}|
[2-9][0-9]\.(?:[0-9]{1,3}\.){2}[0-9]{1,3}|
1[0-6][0-9]\.(?:[0-9]{1,3}\.){2}[0-9]{1,3}|
17[0-1]\.(?:[0-9]{1,3}\.){2}[0-9]{1,3}|
172\.0\.(?:[0-9]{1,3}\.)[0-9]{1,3}|
172\.1[0-5]\.(?:[0-9]{1,3}\.)[0-9]{1,3}|
(172\.3[2-9]\.)(?:[0-9]{1,3}\.)[0-9]{1,3}|
(172\.[4-9][0-9]\.)(?:[0-9]{1,3}\.)[0-9]{1,3}|
...
Run Code Online (Sandbox Code Playgroud)
正则表达式似乎不准确且效率低下,有人有更好的方法来编写正则表达式吗?
Anu*_*ioz 10
试试这个:
^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(?<!172\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31))(?<!127)(?<!^10)(?<!^0)\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(?<!192\.168)(?<!172\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31))\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
Run Code Online (Sandbox Code Playgroud)
它正确地不匹配这个无效的 ips:
999.999.999.999.
108.0.0.01
0.1.2.3
00.0000.00.00
192.168.l.1
912.456.123.123
.3.3.3.0
192.168.o.0
Run Code Online (Sandbox Code Playgroud)
它与本地 IP不匹配:
172.16.0.9
172.16.4.1
172.17.1.1
127.0.0.2
10.0.1.5
10.0.0.1
10.155.155.155
10.255.255.254
172.16.0.4
172.16.0.1
172.17.1.1
172.31.254.254
192.168.1.2
192.168.254.0
Run Code Online (Sandbox Code Playgroud)
并且几乎匹配我测试过的每个 IP。不能说我真的做了很多测试,所以欢迎提出建议
我宁愿捕获每个八位字节并检查子网是否在代码中是私有的,而不是使用正则表达式。不过,我对你的问题很感兴趣。
根据维基百科,有 3 个范围的私有 IP 地址。
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255
Run Code Online (Sandbox Code Playgroud)
现在假设你没有疯狂的类似 IP 的字符串,比如55.300.666.1,你可以使用负回顾来做你想做的事情:
(\d+)(?<!10)\.(\d+)(?<!192\.168)(?<!172\.(1[6-9]|2\d|3[0-1]))\.(\d+)\.(\d+)
Run Code Online (Sandbox Code Playgroud)
让我们再看看,为了清楚起见,添加了一些换行符:
(\d+)(?<!10)
\.(\d+)(?<!192\.168)(?<!172\.(1[6-9]|2\d|3[0-1]))
\.(\d+)\.(\d+)
Run Code Online (Sandbox Code Playgroud)
第一行检查第一个八位字节不是10。第二行检查前 2 个八位字节是否192.168在172.16和之间或不在和 之间172.31。第三行没有什么特别的。正则表达式101
PS:我知道那127.0.0.1是本地主机,但我不知道它是否是私有的(我不是网络工程师)。您可能需要根据需要即兴发挥。
如果您希望验证纯粹的公共 IPv4 地址,我们可以消除所有保留的 IPv4 地址,如下所示:
0.0.0.0/8: 当前网络10.0.0.0/8: 专用网络100.64.0.0/10: 共享地址空间127.0.0.0/8: 环回169.254.0.0/16: 本地链接172.16.0.0/12: 专用网络192.0.0.0/24: IETF 协议分配192.0.2.0/24:TEST-NET-1,文档和示例192.88.99.0/24:IPv6 到 IPv4 中继(包括 2002::/16)192.168.0.0/16: 专用网络198.18.0.0/15: 网络基准测试198.51.100.0/24:TEST-NET-2,文档和示例203.0.113.0/24:TEST-NET-3,文档和示例224.0.0.0/4:IP组播(前D类网络)240.0.0.0/4:保留(原E类网络)255.255.255.255: 播送(列表取自维基百科)
这可以放入一个不使用lookbehinds的简单正则表达式中(因此,正则表达式可以在JavaScript中使用):
(^0\.)|(^10\.)|(^100\.6[4-9]\.)|(^100\.[7-9]\d\.)|(^100\.1[0-1]\d\.)|(^100\.12[0-7]\.)|(^127\.)|(^169\.254\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.0\.0\.)|(^192\.0\.2\.)|(^192\.88\.99\.)|(^192\.168\.)|(^198\.1[8-9]\.)|(^198\.51\.100\.)|(^203.0\.113\.)|(^22[4-9]\.)|(^23[0-9]\.)|(^24[0-9]\.)|(^25[0-5]\.)
Run Code Online (Sandbox Code Playgroud)
同样,这假设您事先已经验证它实际上是一个有效的 IPv4 地址。