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

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

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


person Alex_DeLarge    schedule 18.05.2018    source источник
comment
Простой скрипт Python (из-за этого не публикуется как ответ): import ipaddress,math;print("/" + str(32-math.ceil(math.log2(int(ipaddress.IPv4Address(input()))^2**32-1))))   -  person L3viathan    schedule 18.05.2018


Ответы (4)


Пример функции для RHEL6/RHEL7:

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

В других дистрибутивах Linux параметры ipcalc могут отличаться.

Та же функция без 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}"
}
person Sasha Golikov    schedule 18.05.2018
comment
Версия функции ipcalc ничего не выводит в моей системе (Lubuntu v17.10). Выполнение ipcalc -p 1.1.1.1 255.255.255.0 возвращает ошибку Неизвестная опция: -p. ipcalc версия 0.41-5. - person agc; 19.05.2018
comment
Это работает: ipcalc -n 1.1.1.1 $1 | sed -n '/^Netm/{s#.*= #/#;s/ .*//p;q}' - person agc; 19.05.2018

  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
person agc    schedule 18.05.2018

Решение на основе 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
person Synoli    schedule 02.03.2021

Судя по ответу Саши, этот скрипт работает с 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}"
}
person D.Liu    schedule 18.12.2019