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-я колонка - справочный ответ
- 2-я колонка
IPv4
-эквивалент этой маски подсети, и- 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
[Очки улучшения]
- Вы можете сэкономить память (и операционные затраты на вызовы функций), уменьшив количество определений функций.
- Бинарная маска не может иметь вид «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)) }';