为什么这个 IPv4 的正则表达式不起作用?

Why does this regexp for IPv4 doesn't work?

这是我制作的正则表达式: ^(([01]?\d{1,2})|(2(([0-4]\d)|(5[0-5])))\.){3}(([01]?\d{1,2})|(2(([0-4]\d)|(5[0-5]))))$

我已经使用了几个站点来分解它,看起来它应该可以工作,但没有。期望的结果是匹配任何 IPv4 - 由点分隔的 0 到 255 之间的四个数字。

例如,1.1.1.1 不会为您匹配。 这个问题的目的不是找出 IPv4 地址的正则表达式,而是找出为什么这个看似正确的正则表达式不是。

文字 . 只是捕获组 200-255 部分的一部分:railroad diagram.

这里的 (([01]?\d{1,2})|(2([0-4]\d)|(5[0-5]))\.) 格式不同,可帮助您找出原因:

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

您正在用一个点匹配 0-199 200-255。点以匹配 200-255 为条件。

此外,正如@SebastianProske 指出的那样,2([0-4]\d)|(5[0-5]) 匹配 200-249 50-55,而不是 200-255。

您可以通过添加捕获组来修复正则表达式,但最终我建议不要重新发明轮子并使用 A) 预先存在的正则表达式解决方案或 B) 通过按点拆分来解析 IPv4 地址。后一种方法更容易阅读和理解。

要解决你的问题,只需考虑 前三个 组中的每一个之后的 "decimal":

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

(*请注意,我也颠倒了 2xx 与 1xx 测试的顺序 - 在使用这样的交替时,更喜欢 SPECIAL|...|NORMAL,或者首先限制更多)

see it in action