bash 中 IP 地址/CIDR 的正则表达式

Geo*_*nov 2 bash ip regular-expression

我想检查用户输入是否是 bash 中的有效 IP 地址/CIDR,并且我正在使用正则表达式来执行此操作。所以有效的 CIDR 应该是 0-32,对于 IP,(1-254).(1-255).(1-255).(1-255)/(1-32)所以我当前的代码是:

read -p "Input: " ip_address

if [[ $ip_address =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]];
    then
    echo "VALID"
else
    echo "NOT VALID"
fi
Run Code Online (Sandbox Code Playgroud)

但它过于慷慨并且接受一些无效的组合。因此,有效的 IP 地址/CIDR 组合应该是:10.11.11.11/24或 ,254.255.255.255/23而无效是256.19.11.11/24因为第一个八位字节高于 255 或222.222.222.222/33这里的 CIDR 高于 32。 除了正则表达式之外,还有其他方法来检查有效的 IP 地址/CIDR 吗?

Kus*_*nda 5

要正确处理 IP 地址或 CIDR 的验证,请使用专门为此设计的库函数,例如模块cidrvalidate()中的 Perl 函数Net::CIDR

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid
Run Code Online (Sandbox Code Playgroud)

看看perldoc Net::CIDR这个库还能做什么。

在上面的示例中不是必需的,但可以用于用户的任意输入,否则,如果该输入以 开头--,则该输入将被视为选项。perl-

下面的方法是您尝试的变体,它不关心无效的网络掩码。


0 到 255 之间的正十进制整数可以通过以下方式匹配

[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
Run Code Online (Sandbox Code Playgroud)

0 到 32 之间的正十进制整数可以通过以下方式匹配

[0-9]|[12][0-9]|3[012]
Run Code Online (Sandbox Code Playgroud)

使用这个:

#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(\.$n){3}/$m$ ]]; then
    printf '"%s" is a valid CIDR\n' "$ipaddr"
else
    printf '"%s" is not valid\n' "$ipaddr"
fi
Run Code Online (Sandbox Code Playgroud)

表达方式

^$n(\.$n){3}/$m$
Run Code Online (Sandbox Code Playgroud)

将扩展为跨越给定字符串完整长度的有效 CIDR 的完整正则表达式。


另一种明显的方法是读取给定字符串中的数字并测试前四个数字是否在 0-255 范围内以及第五个数字是否在 0-32 范围内:

#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
    case $var in
        ""|*[!0123456789]*) 
            printf 'not a valid number: %s\n' "$var"
            exit 1
    esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
   [ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
   [ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
   [ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
   [ "$e" -ge 0 ] && [ "$e" -le 32  ]
then
    printf '"%s" is a valid CIDR\n' "$ipaddr"
else
    printf '"%s" is not valid\n' "$ipaddr"
fi
Run Code Online (Sandbox Code Playgroud)

这里我们将五个单词读入五个变量。.输入的字符串在读取时被分割成单词/(这意味着3/3/3/3.2将被解析为有效,但请参见$ipaddr代码)。任何非整数数据读取都会触发脚本退出。然后我们开始根据有效范围测试它们的值。如果任何测试失败,则输入的地址无效。