awk: преобразование маски подсети в префикс

У меня есть сценарий, в котором я сравниваю фактическую таблицу маршрутизации из "netstat -rn" с таблицей маршрутизации, настроенной в собственной конфигурации поставщиков безопасности. Проблема в том, что в то время как netstat -rn выдает маску сети в формате "255.255.255.0", команда для отображения таблицы маршрутизации в поставщике дает ее в виде /24

Мне нужно найти способ создать функцию, используя только awk, для преобразования из маски подсети, например 255.255.255.0, в префикс, например: /24

function subnetmaskToPrefix(subnetmask) {
doing magic
}

subnetmask="255.255.255.0"
prefix=subnetmaskToPrefix(subnetmask)

4 ответа

Решение

Если номер префикса исходит из числа 1 в маске подсети при преобразовании в двоичный файл. пример:

маскировать 255.255.255.0 является 11111111.11111111.11111111.00000000 в двоичном Это 24 1.

echo "255.255.255.0" | awk '
function count1s(N){
    c = 0
    for(i=0; i<8; ++i) if(and(2**i, N)) ++c
    return c
}
function subnetmaskToPrefix(subnetmask) {
    split(subnetmask, v, ".")
    return count1s(v[1]) + count1s(v[2]) + count1s(v[3]) + count1s(v[4])
}
{
    print("/" subnetmaskToPrefix($1))
}'

ты получаешь,

/24

Приведенное ниже решение отлично подходит для gawk. Но если вы не используете gawk, вы можете использовать эту функцию для подсчета.

function count1s(N) {
    r=""                    # initialize result to empty (not 0)
    while(N!=0){            # as long as number still has a value
        r=((N%2)?"1":"0") r   # prepend the modulos2 to the result
        N=int(N/2)            # shift right (integer division by 2)
    }

    # count number of 1s
    r=gsub(/1/,"",r)
    # Return result
    return r

}

так как все1'sв маске подсети сгруппированы вместе на старшей стороне, нет абсолютно никакой необходимости предварительно создавать какие-либо из двоичных битовых строк, поскольку «подсчет переднего фронта 1»` такой же, как

      1.      2^32 (or simply : ( 4 ^ 4 ) ^ 4 ) 
   minus
        integer of subnet mask bits

2. take the log-base-2 value of step-1, which gives you 
   # of 0-bits at the bottom 

   (a tiny 2^-16 has been padded for error-correction), and

3. finally, return `32 minus value of step-2`

проверено и подтверждено в работе mawk, gawk, и nawk

      mawk ' 
function _____(__,_,___,____) {
    return \
    substr(___="[.]" (_=""), __~("["(+_)".]"(+_)) \
    ? sub("^"(+_)"+",_,__) + gsub(___ (+_)"+",".",__):_,_) \
    "subnet-mask::/" (int(\
    log(-(__=____[_ =__ = split(__,____,___)] \
      + (___=_^=_+!--__) * ____[__]       \
      + (___  ^=   --__)  * ____[__]       \
      +  ____[_^!_]*_*___) + ___^(_+=_^=_<_)\
     ) / -log(_) - _^-_^_^_) \
                           + _^_^_*_)
}
BEGIN {  CONVFMT = "%.250g"
    _+= _^= OFMT = "%.25g"
}
($++NF = _____($_))^!_'
  1. 1-я колонка - справочный ответ
  2. 2-я колонкаIPv4-эквивалент этой маски подсети, и
  3. 3-й столбец рассчитанный через функцию
      /0 000.000.000.000 subnet-mask::/0  # this line only included for completeness

/1 128.000.000.000 subnet-mask::/1
/2 192.000.000.000 subnet-mask::/2
/3 224.000.000.000 subnet-mask::/3
/4 240.000.000.000 subnet-mask::/4
/5 248.000.000.000 subnet-mask::/5
/6 252.000.000.000 subnet-mask::/6
/7 254.000.000.000 subnet-mask::/7
/8 255.000.000.000 subnet-mask::/8

/9 255.128.000.000 subnet-mask::/9
/10 255.192.000.000 subnet-mask::/10
/11 255.224.000.000 subnet-mask::/11
/12 255.240.000.000 subnet-mask::/12
/13 255.248.000.000 subnet-mask::/13
/14 255.252.000.000 subnet-mask::/14
/15 255.254.000.000 subnet-mask::/15
/16 255.255.000.000 subnet-mask::/16

/17 255.255.128.000 subnet-mask::/17
/18 255.255.192.000 subnet-mask::/18
/19 255.255.224.000 subnet-mask::/19
/20 255.255.240.000 subnet-mask::/20
/21 255.255.248.000 subnet-mask::/21
/22 255.255.252.000 subnet-mask::/22
/23 255.255.254.000 subnet-mask::/23
/24 255.255.255.000 subnet-mask::/24

/25 255.255.255.128 subnet-mask::/25
/26 255.255.255.192 subnet-mask::/26
/27 255.255.255.224 subnet-mask::/27
/28 255.255.255.240 subnet-mask::/28
/29 255.255.255.248 subnet-mask::/29
/30 255.255.255.252 subnet-mask::/30
/31 255.255.255.254 subnet-mask::/31

[Очки улучшения]

  1. Вы можете сэкономить память (и операционные затраты на вызовы функций), уменьшив количество определений функций.
  2. Бинарная маска не может иметь вид «11101». Следовательно, подцикл (= предварительная функция исходного кода) может быть прерван.

[код]

          awk 'function mask2cidr(mask){
      c=0; split(mask,v,".");
      for(j=1; j<5; j++){for(i=7; i>=0; i--){
        if(and(2**i,v[j])){c++;}else{return c;}
      }}
      return c;
    }
    { print("/" mask2cidr($1)) }';
Другие вопросы по тегам