【问题标题】:Validating IPv4 addresses with regexp使用正则表达式验证 IPv4 地址
【发布时间】:2011-07-14 03:19:18
【问题描述】:

我一直在尝试为 IPv4 验证获取有效的正则表达式,但运气不佳。似乎在某一时刻我使用过(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4},但它产生了一些奇怪的结果:

$ grep --version
grep (GNU grep) 2.7
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.1
192.168.1.1
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.255
192.168.1.255
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.255.255
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.2555
192.168.1.2555

我进行了搜索,看看是否已经有人问过并回答了这个问题,但其他答案似乎只是显示了如何确定 4 组 1-3 个数字,或者对我不起作用。

【问题讨论】:

  • 不要忘记 A、A.B、A.B.C 和 A.B.C.D 一样是 IP 地址的有效形式。严重地。试试ping 2130706433ping 127.1 咯咯笑。
  • 我的变种在线regexr.com/39hqf

标签: regex validation ip-address ipv4 grep


【解决方案1】:

IPv4 地址(准确捕获) 匹配 0.0.0.0 到 255.255.255.255,但会捕获无效地址,例如 1.1.000.1 使用此正则表达式准确匹配 IP 号码。 4 个数字中的每一个都存储在一个捕获组中,因此您可以访问它们以进行进一步处理。

\b
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\b

取自 JGsoft RegexBuddy 库

编辑:这个(\.|$) 部分看起来很奇怪

【讨论】:

  • 不错!我对似乎可行的方法进行了更有效的修改:"\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$){4}\b -- 谢谢!
  • @MatthieuCartier 您的高效正则表达式模式对我不起作用,
  • 255.255.255.000 不是有效 IP
【解决方案2】:

您已经得到了一个可行的答案,但以防万一您好奇您的原始方法出了什么问题,答案是您需要在交替时加上括号,否则只有在数字小于时才需要 (\.|$) 200.

'\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b'
    ^                                    ^

【讨论】:

  • 这似乎也验证了 192.168.1.1.1
  • 应该是:\b((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:(?&lt;!\.)\b|\.)){4};即它以单词边界而不是行尾结束?此外,在这里我标记了非捕获组以避免不需要的子匹配。注意:这仍然没有考虑@dty 的评论,因为我不熟悉这种形式的 IP;尽管他是正确的,这似乎是有效的。
  • 您可能想试试这个:((1?\d\d?|2[0-4]\d|25[0-5])\.){3}(1 ?\d\d?|2[0-4]\d|25[0-5])
  • 09.09.09.09 是否被视为有效 IP?它也被这个正则表达式匹配。但是 ping 会抛出类似ping: cannot resolve 09.09.09.09: Unknown host 的错误消息。我认为将匹配减少为仅点十进制表示法匹配可能是明智的。此entry 讨论了 IP 地址中的前导错误。
  • 不要停在这里,@danail-gabenski 下面的回答提供了另一个处理更多边缘情况的正则表达式。
【解决方案3】:
mysql> select ip from foo where ip regexp '^\\s*[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]\\s*';

【讨论】:

  • 这也匹配0987654.3.2.1
【解决方案4】:
    const char*ipv4_regexp = "\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b";

我将 JGsoft RegexBuddy 库中的正则表达式改编为 C 语言 (regcomp/regexec),我发现它可以工作,但在 Linux 等某些操作系统中存在一些问题。 该正则表达式接受像 192.168.100.009 这样的 ipv4 地址,其中 Linux 中的 009 被认为是八进制值,因此该地址不是您想的那个地址。 我将正则表达式更改如下:

    const char* ipv4_regex = "\\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\."
           "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\."
           "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\."
           "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\b";

现在使用该正则表达式 192.168.100.009 不是有效的 ipv4 地址,而 192.168.100.9 可以。

我也修改了组播地址的正则表达式,如下:

    const char* mcast_ipv4_regex = "\\b(22[4-9]|23[0-9])\\."
                        "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\."
                        "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]?)\\."
                        "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\b";

我认为您必须使正则表达式适应您用于开发应用程序的语言

我在java中放了一个例子:

    package utility;

    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    public class NetworkUtility {

        private static String ipv4RegExp = "\\b(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d?)\\b";

        private static String ipv4MulticastRegExp = "2(?:2[4-9]|3\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d?|0)){3}";

        public NetworkUtility() {

        }

        public static boolean isIpv4Address(String address) {
            Pattern pattern = Pattern.compile(ipv4RegExp);
            Matcher matcher = pattern.matcher(address);

            return matcher.matches();
        }

        public static boolean isIpv4MulticastAddress(String address) {
             Pattern pattern = Pattern.compile(ipv4MulticastRegExp);
             Matcher matcher = pattern.matcher(address);

             return matcher.matches();
        }
    }

【讨论】:

    【解决方案5】:
    ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
    

    接受

    127.0.0.1
    192.168.1.1
    192.168.1.255
    255.255.255.255
    0.0.0.0
    1.1.1.01        # This is an invalid IP address!
    

    拒绝

    30.168.1.255.1
    127.1
    192.168.1.256
    -1.2.3.4
    1.1.1.1.
    3...3
    

    通过单元测试在线尝试:https://www.debuggex.com/r/-EDZOqxTxhiTncN6/1

    【讨论】:

    • “3...3”IP 地址呢?使用此正则表达式接受 3...3
    • 1.1.1.01 怎么样?它是否被视为有效的 IPv4 地址?谢谢。
    • 这个正则表达式 1.1.1.01 被认为是有效的 IPv4 地址。在线单元测试debuggex.com/r/-EDZOqxTxhiTncN6/1
    • 顺便说一句^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$ 得到相同的结果debuggex.com/r/mz_-0dEm3wseIKqK,与@Mark Byers 的答案非常相似
    • @PriteshAcharya 在这里工作得很好。
    【解决方案6】:

    我设法从所有其他答案构建了一个正则表达式。

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

    【讨论】:

    • 根据 IEEE 802.x 以太网标准,IP 验证是 IP 范围 0.x.x.x >>> 不应被允许 - 无效 IP。 #1.IP范围从1.x.x.x到126.x.x.x >>>>可以配置。 #2.IP 范围 127.x.x.x >>>> 不应被允许 - 无效 IP。 #3.IP范围128.x.x.x到223.x.x.x>>可以配置。更好的处理方式建议如下:^(22[0-3]|2[0-1][0-9]|[1][0-9][0-9]?|[1-9 ][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]? )\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-4]|2 [0-4][0-9]|[01]?[0-9][0-9]?)$
    【解决方案7】:

    我正在为 IPv4 地址寻找类似的东西 - 一个正则表达式,它也阻止了常用的私有 IP 地址被验证(192.168.xy、10.xyz、172.16.xy),所以使用负面展望来实现这一点:

    (?!(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.).*)
    (?!255\.255\.255\.255)(25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[1-9])
    (\.(25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|\d)){3}
    

    (当然,这些应该在一行上,为了便于阅读而格式化为 3 行)

    Debuggex Demo

    它可能没有针对速度进行优化,但在仅查找“真实”互联网地址时效果很好。

    将会(并且应该)失败的事情:

    0.1.2.3         (0.0.0.0/8 is reserved for some broadcasts)
    10.1.2.3        (10.0.0.0/8 is considered private)
    172.16.1.2      (172.16.0.0/12 is considered private)
    172.31.1.2      (same as previous, but near the end of that range)
    192.168.1.2     (192.168.0.0/16 is considered private)
    255.255.255.255 (reserved broadcast is not an IP)
    .2.3.4
    1.2.3.
    1.2.3.256
    1.2.256.4
    1.256.3.4
    256.2.3.4
    1.2.3.4.5
    1..3.4
    

    将(并且应该)工作的 IP:

    1.0.1.0         (China)
    8.8.8.8         (Google DNS in USA)
    100.1.2.3       (USA)
    172.15.1.2      (USA)
    172.32.1.2      (USA)
    192.167.1.2     (Italy)
    

    以防万一其他人正在寻找验证“不包括公共私有地址的互联网 IP 地址”

    【讨论】:

    • 演示似乎不再可用。
    【解决方案8】:
    -bash-3.2$ echo "191.191.191.39" | egrep 
      '(^|[^0-9])((2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)\.{3}
         (2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)($|[^0-9])'
    

    &gt;&gt; 191.191.191.39

    (这是一个匹配整个地址空间(包括广播等)的 DFA,仅此而已。

    【讨论】:

      【解决方案9】:

      最新、最短、最不可读的版本(49 个字符

      ^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$

      [0-9] 块可以在 2 个地方用 \d 代替 - 使其可读性降低,但肯定更短。

      更新、更短、可读性第二差的版本(55 个字符

      ^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$

      此版本查找 250-5 的情况,然后巧妙地将所有可能的情况与 200-249100-19910-99 情况进行或运算。请注意,|) 部分不是错误,但实际上对 0-9 范围的最后一种情况进行了 OR 运算。我也省略了?: 非捕获组部分,因为我们并不真正关心捕获的项目,如果我们一开始没有完整匹配,它们就不会被捕获。

      旧版本和短版本(可读性较差)(63 个字符

      ^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$

      旧(可读)版本(70 个字符

      ^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(?!$)|$)){4}$

      它使用负前瞻 (?!) 来消除 ip 可能以 . 结尾的情况

      最早的答案(115 个字符

      ^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}
          (?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$
      

      我认为这是最准确和最严格的正则表达式,它不接受 000.021.01.0. 之类的东西,似乎这里的大多数其他答案都这样做,并且需要额外的正则表达式来拒绝与那个类似的案例 - 即 0 起始数字和一个以.结尾的ip

      【讨论】:

      • 这是迄今为止该主题中唯一正确的答案。其他人错过了0.0.0.0 之类的地址,或者接受了033.033.33.033 之类的混合八进制/十进制表示法,甚至允许使用999.999.999.999。这个比这个答案短 10 个字符的正则表达式怎么样:(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])
      • @tinmarino 我撤消了您的编辑,因为它允许像 192.168.000.1 这样的东西,这不是一个有效的地址。任何希望编辑此答案的人,请先在此处发表评论以避免此类问题 - 我通常会很快回复。当然,总是在寻找更短/更好的解决方案。
      • @DanailGabenski(和其他)用于记忆,你解决了它用1[0-9]{2}|[1-9]?[0-9]替换最后一个[01]?[0-9][0-9]?,因为你不喜欢leading 0。再次感谢!我会将您的解决方案保存在我的正则表达式主行李箱中。
      • @tinmarino 是的,点十进制格式已成为 ipv4 的标准格式,although not officially accepted please look at the following。特别是第 3 点,其中提出了草案但已过期。对验证如此严格的第二个原因是,当在 UI 中显示时,带有非十进制数字(如 023 而不是 23)的 ip 会让用户认为这是一个错误/错误。它还会导致验证/安全性困难,因为需要将 023 转换为 23 以避免重复等。感谢您尝试让事情变得更好!
      • 您可以通过将[0-9] 分解为2[0-4]1 和更短的情况来缩短它。 ^(?:(25[0-5]|(?:2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$
      【解决方案10】:

      我觉得这个是最短的。

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

      【讨论】:

        【解决方案11】:

        这是适合我的正则表达式:
        "\&lt;((([1-9]|1[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-9]|1[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))\&gt;"

        【讨论】:

          【解决方案12】:
          String zeroTo255 = "([0-9]|[0-9][0-9]|(0|1)[0-9][0-9]|2[0-4][0-9]|25[0-5])";
          
          it can contain single digit i.e ([0-9]);  
          It can contain two digits i.e ([0-9][0-9]); 
          range is (099 to 199)i.e((0|1)[0-9][0-9]); 
          range is (200 - 249) i.e (2[0-9][0-9]) ; 
          range is (250-255) i.e(25[0-5]);
          

          【讨论】:

            【解决方案13】:

            我发现这个示例非常有用,而且它允许使用不同的 ipv4 表示法。

            使用python的示例代码:

                def is_valid_ipv4(ip4):
                """Validates IPv4 addresses.
                """
                import re
                pattern = re.compile(r"""
                    ^
                    (?:
                      # Dotted variants:
                      (?:
                        # Decimal 1-255 (no leading 0's)
                        [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
                      |
                        0x0*[0-9a-f]{1,2}  # Hexadecimal 0x0 - 0xFF (possible leading 0's)
                      |
                        0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's)
                      )
                      (?:                  # Repeat 0-3 times, separated by a dot
                        \.
                        (?:
                          [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
                        |
                          0x0*[0-9a-f]{1,2}
                        |
                          0+[1-3]?[0-7]{0,2}
                        )
                      ){0,3}
                    |
                      0x0*[0-9a-f]{1,8}    # Hexadecimal notation, 0x0 - 0xffffffff
                    |
                      0+[0-3]?[0-7]{0,10}  # Octal notation, 0 - 037777777777
                    |
                      # Decimal notation, 1-4294967295:
                      429496729[0-5]|42949672[0-8]\d|4294967[01]\d\d|429496[0-6]\d{3}|
                      42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|
                      4[01]\d{8}|[1-3]\d{0,9}|[4-9]\d{0,8}
                    )
                    $
                """, re.VERBOSE | re.IGNORECASE)
                return pattern.match(ip4) <> None
            

            【讨论】:

              【解决方案14】:
              ((\.|^)(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0$)){4}
              

              这个正则表达式不接受 08.8.8.8 或 8.08.8.8 或 8.8.08.8 或 8.8.8.08

              【讨论】:

              • 这一错过例如 127.0.0.1 和 0.0.0.0
              • ^((\.|^)(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1 -9][0-9]?|[0-9]?|0))((\.|^)(25[0-5]|2[0-4][0-9]|1[0 -9][0-9]|[1-9][0-9]?|0)){2}.((25[0-5]|2[0-4][0-9]|1 [0-9][0-9]|[1-9][0-9]?|0)$)
              • 根据规范拒绝前导零是正确的。
              【解决方案15】:

              只要 IP 包含数字以外的任何字符(在 IP 的后面或前面),就会找到有效的 IP 地址。创建了 4 个反向引用:$+{first}.$+{second}.$+{third}.$+{forth}

              Find String:
              #any valid IP address
              (?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
              #only valid private IP address RFC1918
              (?<IP>(?<![\d])(:?(:?(?<first>10)[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5])))|(:?(?<first>172)[\.](?<second>(:?1[6-9])|(:?2[0-9])|(:?3[0-1])))|(:?(?<first>192)[\.](?<second>168)))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
              
              Notepad++ Replace String Option 1: Replaces the whole IP (NO Change):
              $+{IP}
              
              Notepad++ Replace String Option 2: Replaces the whole IP octect by octect (NO Change)
              $+{first}.$+{second}.$+{third}.$+{forth}
              
              Notepad++ Replace String Option 3: Replaces the whole IP octect by octect (replace 3rd octect value with 0)
              $+{first}.$+{second}.0.$+{forth}
              NOTE: The above will match any valid IP including 255.255.255.255 for example and change it to 255.255.0.255 which is wrong and not very useful of course.
              

              用实际值替换每个八位字节的一部分,但是您可以构建自己的查找和替换,这对于修改文本文件中的 IP 非常有用:

              for example replace the first octect group of the original Find regex above:
              (?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))
              with
              (?<first>10)
              
              and
              (?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))
              with
              (?<second>216)
              and you are now matching addresses starting with first octect 192 only
              
              Find on notepad++:
              (?<IP>(?<![\d])(?<first>10)[\.](?<second>216)[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
              

              您仍然可以使用与以前完全相同的方式使用反向引用组执行替换。

              您可以在下面了解上面的匹配方式:

              cat ipv4_validation_test.txt
              Full Match:
              0.0.0.1
              12.108.1.34
              192.168.1.1
              10.249.24.212
              10.216.1.212
              192.168.1.255
              255.255.255.255
              0.0.0.0
              
              
              Partial Match (IP Extraction from line)
              30.168.1.0.1
              -1.2.3.4
              sfds10.216.24.23kgfd
              da11.15.112.255adfdsfds
              sfds10.216.24.23kgfd
              
              
              NO Match
              1.1.1.01
              3...3
              127.1.
              192.168.1..
              192.168.1.256
              da11.15.112.2554adfdsfds
              da311.15.112.255adfdsfds
              

              使用 grep 可以看到如下结果:

              From grep:
              grep -oP '(?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
              0.0.0.1
              12.108.1.34
              192.168.1.1
              10.249.24.212
              10.216.1.212
              192.168.1.255
              255.255.255.255
              0.0.0.0
              30.168.1.0
              1.2.3.4
              10.216.24.23
              11.15.112.255
              10.216.24.23
              
              
              grep -P '(?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
              0.0.0.1
              12.108.1.34
              192.168.1.1
              10.249.24.212
              10.216.1.212
              192.168.1.255
              255.255.255.255
              0.0.0.0
              30.168.1.0.1
              -1.2.3.4
              sfds10.216.24.23kgfd
              da11.15.112.255adfdsfds
              sfds10.216.24.23kgfd
              
              
              #matching ip addresses starting with 10.216
              grep -oP '(?<IP>(?<![\d])(?<first>10)[\.](?<second>216)[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
              10.216.1.212
              10.216.24.23
              10.216.24.23
              

              【讨论】:

                【解决方案16】:

                这比一些长一点,但这是我用来匹配 IPv4 地址的。简单却不妥协。

                ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$
                

                【讨论】:

                  【解决方案17】:

                  IPv4 地址是个很复杂的东西。

                  注意:缩进和衬里仅用于说明目的,在真正的 RegEx 中不存在。

                  \b(
                    ((
                      (2(5[0-5]|[0-4][0-9])|1[0-9]{2}|[1-9]?[0-9])
                    |
                      0[Xx]0*[0-9A-Fa-f]{1,2}
                    |
                      0+[1-3]?[0-9]{1,2}
                    )\.){1,3}
                    (
                      (2(5[0-5]|[0-4][0-9])|1[0-9]{2}|[1-9]?[0-9])
                    |
                      0[Xx]0*[0-9A-Fa-f]{1,2}
                    |
                      0+[1-3]?[0-9]{1,2}
                    )
                  |
                    (
                      [1-3][0-9]{1,9}
                    |
                      [1-9][0-9]{,8}
                    |
                      (4([0-1][0-9]{8}
                        |2([0-8][0-9]{7}
                          |9([0-3][0-9]{6}
                            |4([0-8][0-9]{5}
                              |9([0-5][0-9]{4}
                                |6([0-6][0-9]{3}
                                  |7([0-1][0-9]{2}
                                    |2([0-8][0-9]{1}
                                      |9([0-5]
                      ))))))))))
                    )
                  |
                    0[Xx]0*[0-9A-Fa-f]{1,8}
                  |
                    0+[1-3]?[0-7]{,10}
                  )\b
                  

                  这些 IPv4 地址由上述 RegEx 验证。

                  127.0.0.1
                  2130706433
                  0x7F000001
                  017700000001
                  0x7F.0.0.01 # Mixed hex/dec/oct
                  000000000017700000001 # Have as many leading zeros as you want
                  0x0000000000007F000001 # Same as above
                  127.1
                  127.0.1
                  

                  这些都被拒绝了。

                  256.0.0.1
                  192.168.1.099 # 099 is not a valid number
                  4294967296 # UINT32_MAX + 1
                  0x100000000
                  020000000000
                  

                  【讨论】:

                    【解决方案18】:

                    带子网掩码:

                    ^$|([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\
                    .([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\
                    .([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\
                    .([01]?\\d\\d?|2[0-4]\\d|25[0-5])
                    ((/([01]?\\d\\d?|2[0-4]\\d|25[0-5]))?)$
                    

                    【讨论】:

                      【解决方案19】:

                      ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.)){3}+((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$


                      上面将是 ip 地址的正则表达式,例如: 221.234.000.112 也适用于 221.234.0.112、221.24.03.112、221.234.0.1


                      你可以想象上面的各种地址

                      【讨论】:

                        【解决方案20】:
                        (((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2}))\.){3}(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2})))
                        

                        测试以查找文本中的匹配项, https://regex101.com/r/9CcMEN/2

                        以下是定义IP地址每个数字的有效组合的规则:

                        • 任何一位或两位数字。
                        • 任何以1开头的三位数字。

                        • 任何以2 开头的三位数字,如果第二位数字是0 通过4

                        • 任何以25 开头的三位数字,如果第三位数字是0 通过5

                        让我们从 (((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2}))\.) 开始,这是一组四个嵌套的子表达式,我们将按相反的顺序查看它们。 (\d{1,2}) 匹配任何一位或两位数字或数字 099(1\d{2}) 匹配以1 开头的任何三位数字(1 后跟任意两位数字),或数字100199(2[0-4]\d) 匹配数字 200249(25[0-5]) 匹配数字 250255。这些子表达式中的每一个都包含在另一个子表达式中,每个子表达式之间都有一个|(因此四个子表达式中的一个必须匹配,而不是全部匹配)。在数字范围到达\. 以匹配. 之后,然后将整个系列(所有数字选项加上\.)包含在另一个子表达式中并使用{3} 重复三次。最后,重复数字范围(这次没有尾随的\.)以匹配最终的 IP 地址编号。通过将四个数字中的每一个限制为0255 之间的值,这种模式确实可以匹配有效的IP 地址并拒绝无效的地址。

                        摘自:Ben Forta. “Learning Regular Expressions.”


                        如果 IP 地址的开头和结尾都不需要字符,则应分别使用 ^$ 元字符。

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

                        测试以查找文本中的匹配项, https://regex101.com/r/uAP31A/1

                        【讨论】:

                          【解决方案21】:

                          我会使用 PCRE 和 define 关键字:

                          /^
                           ((?&byte))\.((?&byte))\.((?&byte))\.((?&byte))$
                           (?(DEFINE)
                               (?<byte>25[0-5]|2[0-4]\d|[01]?\d\d?))
                          /gmx
                          

                          演示:https://regex101.com/r/IB7j48/2

                          这样做的原因是为了避免重复(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) 模式四次。其他解决方案(例如下面的解决方案)效果很好,但它并没有像许多人所要求的那样捕获每个组。

                          /^((\d+?)(\.|$)){4}/ 
                          

                          拥有 4 个捕获组的唯一其他方法是重复该模式四次:

                          /^(?<one>\d+)\.(?<two>\d+)\.(?<three>\d+)\.(?<four>\d+)$/
                          

                          因此在 perl 中捕获 ipv4 非常容易

                          $ echo "Hey this is my IP address 138.131.254.8, bye!" | \
                            perl -ne 'print "[$1, $2, $3, $4]" if \
                              /\b((?&byte))\.((?&byte))\.((?&byte))\.((?&byte))
                               (?(DEFINE)
                                  \b(?<byte>25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))
                              /x'
                          
                          [138, 131, 254, 8]
                          

                          【讨论】:

                            【解决方案22】:

                            我能想象到的最精确、最直接、最紧凑的 IPv4 正则表达式是

                            ^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$
                            

                            但是......的性能/效率呢?抱歉,我不知道,谁在乎?

                            【讨论】:

                              【解决方案23】:

                              我认为许多阅读这篇文章的人会寻找更简单的正则表达式,即使它们匹配一些技术上无效的 IP 地址。 (而且,正如其他地方所指出的,正则表达式可能不是正确验证 IP 地址的正确工具。)

                              删除^ 并在适用的情况下将$ 替换为\b,如果您不想匹配行的开头/结尾。

                              基本正则表达式 (BRE)(在 GNU grep、GNU sed 和 vim 上测试):

                              /^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/
                              

                              扩展正则表达式 (ERE):

                              /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/
                              

                              或:

                              /^([0-9]+(\.|$)){4}/
                              

                              与 Perl 兼容的正则表达式 (PCRE)(在 Perl 5.18 上测试):

                              /^\d+\.\d+\.\d+\.\d+$/
                              

                              或:

                              /^(\d+(\.|$)){4}/
                              

                              Ruby(在 Ruby 2.1 上测试):

                              虽然应该是 PCRE,但 Ruby 出于某种原因允许 Perl 5.18 不允许使用此正则表达式:

                              /^(\d+[\.$]){4}/
                              

                              我对所有这些的测试都在线here

                              【讨论】:

                                【解决方案24】:

                                试试这个:

                                \b(([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.(2[0-5][0-5]|1[0-9][0-9]|[1-9][0-9]|[1-9]))\b
                                

                                【讨论】:

                                  【解决方案25】:
                                  ip address can be from 0.0.0.0 to 255.255.255.255
                                  
                                  (((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])[.]){3}((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])$
                                  
                                  (0|1)?[0-9][0-9]? - checking value from 0 to 199
                                  2[0-4][0-9]- checking value from 200 to 249
                                  25[0-5]- checking value from 250 to 255
                                  [.] --> represent verify . character 
                                  {3} --> will match exactly 3
                                  $ --> end of string
                                  

                                  【讨论】:

                                    【解决方案26】:

                                    以上答案是有效的,但是如果 IP 地址不在行尾并且在文本之间怎么办。这个正则表达式甚至可以解决这个问题。

                                    代码:'\b((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.)){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\b'

                                    输入文本文件:

                                    ip address 0.0.0.0 asfasf
                                     sad sa 255.255.255.255 cvjnzx
                                    zxckjzbxk  999.999.999.999 jshbczxcbx
                                    sjaasbfj 192.168.0.1 asdkjaksb
                                    oyo 123241.24121.1234.3423 yo
                                    yo 0000.0000.0000.0000 y
                                    aw1a.21asd2.21ad.21d2
                                    yo 254.254.254.254 y0
                                    172.24.1.210 asfjas
                                    200.200.200.200
                                    000.000.000.000
                                    007.08.09.210
                                    010.10.30.110
                                    

                                    输出文本:

                                    0.0.0.0
                                    255.255.255.255
                                    192.168.0.1
                                    254.254.254.254
                                    172.24.1.210
                                    200.200.200.200
                                    

                                    【讨论】:

                                    • 这被标记为负面,直到我给它投票。我一直在努力做到这一点(比我想承认的要多几个小时)。它不会捕获一条线上有多个点四边形的线,但对于我的用例,我可以忍受。这是一个很好的答案,它需要更多的选票!
                                    【解决方案27】:

                                    以下是验证 IP 地址的正则表达式。

                                    ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
                                    

                                    【讨论】:

                                      【解决方案28】:

                                      简单的方法

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

                                      Demo

                                      【讨论】:

                                        【解决方案29】:

                                        ''' 这段代码对我有用,就这么简单。

                                        这里我取了 ip 的值,我正在尝试用正则表达式匹配它。

                                        ip="25.255.45.67"    
                                        
                                        op=re.match('(\d+).(\d+).(\d+).(\d+)',ip)
                                        
                                        if ((int(op.group(1))<=255) and (int(op.group(2))<=255) and int(op.group(3))<=255) and (int(op.group(4))<=255)):
                                        
                                        print("valid ip")
                                        
                                        else:
                                        
                                        print("Not valid")
                                        

                                        上述条件检查所有 4 个八位字节的值是否超过 255,那么它是无效的。但在应用条件之前,我们必须将它们转换为整数,因为值是在字符串中。

                                        group(0) 打印匹配的输出,而 group(1) 打印第一个匹配的值,这里是“25”,依此类推。 '''

                                        【讨论】:

                                        • 欢迎来到 *。如果您可以花一些话来说明为什么您的答案应该解决 OP 问题,那就太好了。只有代码的答案通常是不好的答案,因为它们无法帮助其他编码人员了解他们做错了什么。
                                        • 在您的代码中使用适当的缩进以使其对用户可读
                                        【解决方案30】:

                                        这个只匹配有效的IP(没有前置0,但它会匹配从0-255的八位字节,不管它们的“功能”[即保留、私有等])并允许内联匹配,其中可能有空格和/或在 IP 之后,或在使用 CIDR 表示法时。

                                        grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)'
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.2'
                                        10.0.1.2
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2'
                                        ip address 10.0.1.2
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2 255.255.255.255'
                                        ip address 10.0.1.2 255.255.255.255
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2/32'
                                        ip address 10.0.1.2/32
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2.32'
                                        $
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address10.0.1.2'
                                        $
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.256'
                                        $
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '0.0.0.0'
                                        0.0.0.0
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.255'
                                        255.255.255.255
                                        
                                        $ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.256'
                                        $
                                        

                                        当然,如果 IP 是内联的,您可以使用 grep 选项“-o”,如果您只想要整个 IP 而只需要 IP,则可以使用空格修剪器。

                                        对于我们这些使用python的人来说,大致相当于:

                                        >>> ipv4_regex = re.compile(r'(^| )((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])($| |/)')
                                        >>> ipv4_regex.search('ip address 10.1.2.3/32')
                                        <re.Match object; span=(10, 20), match=' 10.1.2.3/'>
                                        

                                        如果您像我一样挑剔(懒惰),您可能更喜欢使用分组来获取整个 IP,只获取 IP,或者 CIDR,只获取 CIDR 或它们的某种组合。我们可以使用(?P) syntax 为我们的群组命名以便于参考。

                                        >>> ipv4_regex = re.compile(r'(?:^| )(?P<address>((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]))(?P<slash>/)?(?(slash)(?P<cidr>[0-9]|[12][0-9]|3[0-2]))(?:$| )')
                                        >>> match = ipv4_regex.search('ip address 10.0.1.2/32')
                                        >>> match.group('address')
                                        '10.0.1.2'
                                        >>> match.group('cidr')
                                        '32'
                                        >>> "".join((match.group('address'), match.group('slash'), match.group('cidr')))
                                        '10.0.1.2/32'
                                        

                                        当然,有一些方法可以不只使用正则表达式。这里有一些你可以检查的条件(这个没有找到内联的,只是验证传递的地址是有效的)。

                                        首先检查地址中的每个字符是数字还是'.'

                                        接下来检查是否正好有 3 个 '.'

                                        接下来的两次检查检查每个八位字节是否在 0 到 255 之间。

                                        最后的检查是没有八位字节以'0'开头

                                        def validate_ipv4_address(address):
                                            return all(re.match('\.|\d', c) for c in address) \
                                                and address.count('.') == 3 \
                                                and all(0 <= int(octet) <= 255 for octet in address.split('.')) \
                                                and all((len(bin(int(octet))) <= 10 for octet in address.split('.'))) \
                                                and all(len(octet) == 1 or d[0] != '0' for octet in address.split('.'))
                                        
                                        
                                        >>> validate_ipv4_address('255.255.255.255')
                                        True
                                        >>> validate_ipv4_address('10.0.0.1')
                                        True
                                        >>> validate_ipv4_address('01.01.01.01')
                                        False
                                        >>> validate_ipv4_address('123.456.789.0')
                                        False
                                        >>> validate_ipv4_address('0.0.0.0')
                                        True
                                        >>> validate_ipv4_address('-1.0.0.0')
                                        False
                                        >>> validate_ipv4_address('1.1.1.')
                                        Traceback (most recent call last):
                                          File "<stdin>", line 1, in <module>
                                          File "<stdin>", line 4, in validate_ipv4_address
                                          File "<stdin>", line 4, in <genexpr>
                                        ValueError: invalid literal for int() with base 10: ''
                                        >>> validate_ipv4_address('.1.1.1')
                                        Traceback (most recent call last):
                                          File "<stdin>", line 1, in <module>
                                          File "<stdin>", line 4, in validate_ipv4_address
                                          File "<stdin>", line 4, in <genexpr>
                                        ValueError: invalid literal for int() with base 10: ''
                                        >>> validate_ipv4_address('1..1.1')
                                        Traceback (most recent call last):
                                          File "<stdin>", line 1, in <module>
                                          File "<stdin>", line 4, in validate_ipv4_address
                                          File "<stdin>", line 4, in <genexpr>
                                        ValueError: invalid literal for int() with base 10: ''
                                        

                                        (按位,每个八位字节应为 8 位或更少,但每个八位字节都以 '0b' 开头)

                                        >>> bin(0)
                                        '0b0'
                                        >>> len(bin(0))
                                        3
                                        >>> bin(255)
                                        '0b11111111'
                                        >>> len(bin(256))
                                        11
                                        

                                        【讨论】: