【问题标题】:Regular expression for subnet masking?子网掩码的正则表达式?
【发布时间】:2011-03-19 07:19:31
【问题描述】:

我正在使用正则表达式来检查子网掩码。我使用带有掩码值的 ajax txtbox 但这不起作用,然后我切换到一个文本框并为此应用正则表达式。不幸的是,一个也不工作。

你能帮我提供一个用于子网掩码 255.255.255.255 的 RE

或者有什么最好的方法吗?

解决方案

我使用的是蒙版文本框,不知道如何输入验证表达式。

最后我找到了一个蒙版文本框的属性作为验证表达式,然后我把 RE 放在那里并将属性 validate 更改为 true。

无需显式使用验证器表达式。

谢谢

【问题讨论】:

  • 我认为编写一个将掩码转换为整数并检查左侧(msb)侧的连续位的函数会更快更容易。
  • 通过阅读此freesoft.org/CIE/Course/Subnet/6.htm 似乎“有效”数字的数量非常少。

标签: c# asp.net


【解决方案1】:

要使用正则表达式执行此操作,您必须确保整个 IPv4 点式四边形表示一个 32 位数字,其中只有前导数字。确保四边形中的每个数字只有前导数是不够的。例如,255.192.255.0 不是有效的子掩码,即使四边形中的每个数字只有前导数字。基于@xanatos 提供的解决方案,

var leadingOnes = new Regex("255|254|252|248|240|224|192|128|0+");

定义一个正则表达式,它将匹配任何 8 位(十进制)数字和前导数字。我使用“0+”来允许 .000,有时在四边形中使用。显然,如果您想强制一个零,请改用“0”。

然后您必须构建一个匹配以下四种模式中的任何一种的正则表达式,我将其表示为伪正则表达式以使其更易于理解:

  • 255.255.255.领先的
  • 255.255.leadingOnes*.0
  • 255.leadingOnes.0.0
  • 领先的.0.0.0

您可以将其写为单个字符串,也可以通过串联构建它。这是构建它:

var leadingOnes = "(255|254|252|248|240|224|192|128|0+);"
var allOnes = @"(255\.)"; 
var re = new Regex("^((" + allOnes + "{3}" + leadingOnes + ")|" +
                     "(" + allOnes + "{2}" + leadingOnes + @"\.0+)|" +
                     "(" + allOnes +         leadingOnes + @"(\.0+){2})|" +
                     "(" +                   leadingOnes + @"(\.0+){3}))$");

如果我们忽略换行符,这是整个字符串。

var re = new Regex(@"^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$");

按照@Keith 的建议,您可以从一个简单的正则表达式开始,例如

Regex("([0-9]{1,3}\.){3}[0-9]{1,3}" 得到四个由点分隔的 3 位数字,然后编写一个函数,将这四个部分提取并计算为一个 32 位整数,然后检查以确保它只有前导数。 有几种方法可以做到这一点,但它们都需要多达 31 次比较操作才能完成验证。

【讨论】:

  • 你可以很容易地检查一个 int 是否只包含一些位算术和单个比较​​的前导:i == i | (i << 1)
  • 如果其他人在上面使用,上面分配给leadingOnes 的字符串在224192 之间缺少|
  • 糟糕,我忘了说我没有找到丢失的管道错误,pmarquis 找到了。
  • 谢谢@Dave。固定的。很难相信这个答案已经存在了四年半,却没有被注意到。
【解决方案2】:

如果您想接受任何 IP 地址作为子网掩码:

var num = @"(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
var rx = new Regex("^" + num + @"\." + num + @"\." + num + @"\." + num + "$");

我认为将“重复”匹配拆分为单独变量中的一组数字更容易。

作为读者练习,我将给出表达式的另一种变体。这将捕获同一组中的所有数字,但捕获不同:

var rx = new Regex("^(?:" + num + @"(?:\.(?!$)|$)){4}$");

但是错了,你应该用这个

var num = @"(255|254|252|248|240|224|192|128|0+)";
var rx = new Regex("^" + num + @"\." + num + @"\." +num + @"\." +num + "$");

var rx = new Regex("^(?:" + num + @"(?:\.(?!$)|$)){4}$");

http://www.freesoft.org/CIE/Course/Subnet/6.htm

【讨论】:

  • 这很接近,但并非完全正确。例如,此代码会将 254.0.0.0 标记为有效(不是)。它还会将 255.255.0.128 之类的东西标记为有效(不是)。最好的方法是将 IP 地址转换为位并检查第一次出现的“0”并从那里开始。 kthx.at/subnetmask
【解决方案3】:

我知道有人问过关于 Regex 表达式的问题,但对于其他感兴趣的人,这里有两个针对该问题的迭代解决方案。第二个函数比第一个函数快一点。

private bool IsValidSubnet(IPAddress ip) {
    byte[] validOctets = new byte[] { 255, 254, 252, 248, 240, 224, 192, 128, 0 };
    byte[] ipOctets = ip.GetAddressBytes();
    bool restAreZeros = false;
    for (int i = 0; i < 4; i++) {
        if (!validOctets.Contains(ipOctets[i]))
            return false;
        if (restAreZeros && ipOctets[i] != 0)
            return false;
        if (ipOctets[i] < 255)
            restAreZeros = true;
    }
    return true;
}

// checks if the address is all leading ones followed by only zeroes
private bool IsValidSubnet2(IPAddress ip) {
    byte[] ipOctets = ip.GetAddressBytes();
    bool restAreOnes = false;
    for (int i = 3; i >= 0; i--) {
        for (int j = 0; j < 8; j++) {
            bool bitValue = (ipOctets[i] >> j & 1) == 1;
            if (restAreOnes && !bitValue)
                return false;
            restAreOnes = bitValue;
        }
    }
    return true;
}

【讨论】:

    【解决方案4】:

    来自http://pastebin.com/wTEKjKpP

    var subnetRegex = /^((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0)|255\.(0|128|192|224|240|248|252|254)))))$/
    

    当然,这适用于 javascript,但这应该会有所帮助。

    【讨论】:

      【解决方案5】:

      您可以使用此正则表达式来验证子网

      ^(((255\.){3}(255|254|252|248|240|224|192|128+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$ 
      

      【讨论】:

        【解决方案6】:

        说明

        聚会有点晚了,但我们不能只对有效八位字节进行正则表达式检查,因为:

        1. 子网必须以 255.X.X.X 开头
        2. 子网不能如下所示:255.254.128.X - 一旦有 0 位,其他所有位都必须为 0

        执行此操作的正确方法是从 MSB 遍历位,检查第一个 0 位。找到第一个 0 位后,检查它的位置。最大的合法子网是 /8 或 255.0.0.0,这意味着在第一个 0 之前需要有 8 个 1 位。然后,确保第一个 0 之后的每一位都是零。综上所述:

        1. (可选择验证它是否是有效的 IP 地址...)

        2. 从 MSB 开始,向下查找第一个 0

        3. 如果您找到 0(255.255.255.255 仍然有效),请检查位置
        4. 检查所有剩余位是否为零

        代码

            private bool IsValidSubnet(string subnet)
            {
                //A subnet is a valid ipv4 address, so start checking there
                if (!IsIPv4(subnet)) return false;
        
                // Get the 4 bytes
                byte[] subnetMaskBytes =
                            System.Net.IPAddress.Parse(subnet).GetAddressBytes();
        
                //Shift to get uint representation of the bits
                var UintSubnet = (uint)subnetMaskBytes[0] << 24;
                UintSubnet += (uint)subnetMaskBytes[1] << 16;
                UintSubnet += (uint)subnetMaskBytes[2] << 8;
                UintSubnet += (uint)subnetMaskBytes[3];
        
                int i = 31;
                while (i >= 0)
                {
                    UInt32 mask = (UInt32)(1 << i);
                    if ((UintSubnet & mask) == 0) break;
                    i--;
                }
        
                // It is not legal to have fewer than 8 bits of addressing
                if (i >= 24) return false;
        
                // Make sure that all remaining bits are 0
                while (i >= 0)
                {
                    UInt32 mask = (UInt32)(1 << i);
                    if ((UintSubnet & mask) != 0) return false;
                    i--;
                }
                return true;
            }
        

        【讨论】:

          猜你喜欢
          • 2019-08-08
          • 2022-11-22
          • 1970-01-01
          • 1970-01-01
          • 2013-07-31
          • 2013-04-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多