Bash - конвертировать сетевую маску в нотации CIDR?

Пример: у меня есть маска сети: 255.255.255.0

Есть ли в bash команда или простой скрипт для преобразования моей сетевой маски в нотацию /24?

4 ответа

Решение

Пример функции для Linux:

IPprefix_by_netmask() {
#function returns prefix for given netmask in arg1
 ipcalc -p 1.1.1.1 $1 | sed -n 's/^PREFIX=\(.*\)/\/\1/p'
}

Результат:

$ IPprefix_by_netmask 255.255.255.0
/24

Та же функция без ipcalc, протестированная в Solaris и Linux:

IPprefix_by_netmask() {
    #function returns prefix for given netmask in arg1
    bits=0
    for octet in $(echo $1| sed 's/\./ /g'); do 
         binbits=$(echo "obase=2; ibase=10; ${octet}"| bc | sed 's/0//g') 
         let bits+=${#binbits}
    done
    echo "/${bits}"
}
  1. Использование функции subnetcalc:

    IPprefix_by_netmask() {
        subnetcalc 1.1.1.1 "$1" -n  | sed -n '/^Netw/{s#.*/ #/#p;q}'
    }
    
  2. В чистом виде bash, преобразуйте IP в длинную восьмеричную строку и суммируйте ее биты:

    IPprefix_by_netmask () { 
       c=0 x=0$( printf '%o' ${1//./ } )
       while [ $x -gt 0 ]; do
           let c+=$((x%2)) 'x>>=1'
       done
       echo /$c ; }
    

Выход из IPprefix_by_netmask 255.255.255.0 (любая функция):

/24

Решение на основе awk

Хотя GNU awk не является Bash, он установлен по умолчанию в достаточном количестве дистрибутивов, поэтому это может быть полезно в смысле вопроса:

      awk -F. '{
    split($0, octets)
    for (i in octets) {
        mask += 8 - log(2**8 - octets[i])/log(2);
    }
    print "/" mask
}' <<< 255.255.255.240

Это печатает:

      /28

Судя по ответу Саши, этот скрипт работает с dash (протестировано с Ubuntu 18.04):

IPprefix_by_netmask() {
    #function returns prefix for given netmask in arg1
    bits=0
    for octet in $(echo $1| sed 's/\./ /g'); do 
         binbits=$(echo "obase=2; ibase=10; ${octet}"| bc | sed 's/0//g') 
         bits=$(expr $bits + ${#binbits})
    done
    echo "/${bits}"
}
Другие вопросы по тегам