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

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

我想检查用户输入是否是 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

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

答案1

要正确处理 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

看看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]

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

[0-9]|[12][0-9]|3[012]

使用这个:

#!/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

表达方式

^$n(\.$n){3}/$m$

将扩展为跨越给定字符串完整长度的有效 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

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

答案2

这就是我用的:

#!/bin/bash
function checkCidrFormat {
  local ipCidr="${1}"
  local validIpCidr
  validIpCidr='(^([1-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])\.([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])\.([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])\.([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])\/([1-9]|[1-2][0-9]|[3][0-2]))$'
  if [[ $ipCidr =~ ^$validIpCidr ]]; then
    echo "valid format"
    return 0
  else
    echo "not valid format"
    return 1
  fi
}

while true;
do
read -rp "ip cidr (eg. 172.16.16.32/27): " cidr
if checkCidrFormat "${cidr}"; then
  echo "do something"
fi
done

相关内容