正则表达式仅匹配公共 IPv4 地址

Mat*_*son 3 regex

起初,我认为在互联网上很容易找到只匹配公共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。不能说我真的做了很多测试,所以欢迎提出建议


Cod*_*ent 6

我宁愿捕获每个八位字节并检查子网是否在代码中是私有的,而不是使用正则表达式。不过,我对你的问题很感兴趣。

根据维基百科,有 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.168172.16和之间或不在和 之间172.31。第三行没有什么特别的。正则表达式101

PS:我知道那127.0.0.1是本地主机,但我不知道它是否是私有的(我不是网络工程师)。您可能需要根据需要即兴发挥。

  • 127.0.0.1 到 127.255.255.255 的整个 IP 范围不被视为“公共 IP 地址”,并且不应与公共 IP 范围匹配。 (2认同)

Irv*_*Lim 5

如果您希望验证纯粹的公共 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 地址。