使用正则表达式验证IPv4地址

206

我一直在尝试获得一个高效的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

我搜索过,看是否已经有人问过并得到了回答,但其他答案似乎仅展示如何确定由1-3个数字组成的4组数字,或者对我没有用。


22
别忘了 A、A.B 和 A.B.C 也是有效的 IP 地址格式,不只是 A.B.C.D。真的,请尝试用“ping 2130706433”和“ping 127.1”,可以让你发笑。 - dty
1
我的变量在线 https://regexr.com/39hqf - Enginer
47个回答

0

我在这个页面看到了非常糟糕的正则表达式..所以我用自己的来替换:

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

内容解释:
num-group = (0-9|10-99|100-199|200-249|250-255)
<border> + { <num-group> + <dot-cahracter> }x3 + <num-group> + <border>

在这里,您可以验证它是如何工作的这里


0

这个只匹配有效的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而无其他内容。
对于我们使用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)语法为我们的组命名,以便更轻松地引用它们。
>>> 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: ''

(按位运算,每个八位字节或更少,但每个字节都以“0b”为前缀)

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

0

我发现这个示例非常有用,而且它允许使用不同的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

0

尝试使用URL构造函数

const validateIPAddress = (ipAddress) => {
  try {
    new URL(`http://${ipAddress}`);
    return true;
  } catch (error) {
    alert("Wrong IP Address");
    return false;
  }
}

-2

这是我使用的正则表达式:
"\<((([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]))\>"


-3

^\\s*[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]\\s*


3
这也将匹配 0987654.3.2.1 - memowe

-3
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]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接