LINUX.ORG.RU

Перевести hex2bin с ведущими нулями, и затем посчитать еденицы.


0

2

Есть скрипт, который заходит на коммутатор и смотрит, на каких портах есть VLAN 2, но ответ от коммутатора приходит ввиде HEX значения (маски портов):

snmpwalk -v2c -O vq -c private 10.0.0.2 SNMPv2-SMI::mib-2.17.7.1.4.3.1.2.2
"20 80 00 00 00 00 00 00 " 
20 80 00 00 00 00 00 00 -> 0010 0000 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
То есть VLAN есть на 3 и 9 портах.
snmpwalk -v2c -O vq -c private 10.0.0.3 SNMPv2-SMI::mib-2.17.7.1.4.3.1.2.2
"00 00 01 00 "
00 00 01 00 ->0000 0000 0000 0000 0000 0001 0000 0000
То есть VLAN есть на 24порту.
Как осуществить этот перевод на баше я не могу придумать. Проблема осложняется тем что длинна может быть разной: либо 32 либо 64 (зависит от коммутатора). Но тут можно откинуть половину у длинной строки тк. портов точно не больше 32. А вот дальше, при попытке перевести:
echo "ibase=16; obase=2; 2080000000000000" | bc 
10000010000000000000000000000000000000000000000000000000000000
#Не хватает нулей.
printf %032d  `echo "ibase=16; obase=2; 20800000" | bc`
printf: warning: 100000100000000000000000000000: Numerical result out of range
Решение: разделить отбросить половину у длинного (оставить 8 цифр) и разделить пополам (по 4) что бы принтф не ругался:
members1=`echo $members | awk '{ print $1 $2 }' | sed -s 's/\"//'` 
memvers1bin=`echo "ibase=16; obase=2; $members1" | bc`
members2=`echo $members | awk '{ print $3 $4 }' | sed -s 's/\"//'`
members2bin=`echo "ibase=16; obase=2; $members2" | bc`
members=`printf %016d $members1bin $members2bin`
А теперь вопрос: как полученую последовательность преобразовать в цифру? как я понимаю нужно перебирать по очереди цифры и если встречается 1 возвращать текущий счетчик. но как это сделать - туплю.

И второй вопрос: если ли более локаничный способ обойти переволнение в принтф?


Ответ на: комментарий от four_str_sam

В С не силен, увы. Задача банальная, и сделать это можно за день (даже с нуля научиться) но сделать надо срочно. по этому что быстрее под руку попалось).

DeeZ ()
Ответ на: комментарий от DeeZ

Что бы вывести часть строки STR echo ${STR:N:M}, где N - номер символа с которого будет отображена строка, а M - количество отображаемых символов. И в цикле выводишь символы Лучше, наверное, исходную строку разбивать на байты

four_str_sam ()

еденицы.

единицы

#!/bin/bash

function decode() {
  OIFS=$IFS
  IFS=' '
  for x in $1
  do
    x=`echo "ibase=16; obase=2; $x" | bc`
    printf "%08d" $x
  done
  IFS=$OIFS
}
decode "20 08 01 00"
anonymous ()

составь таблицу hex->bin (16 значений), чтобы не напрягаться с башем и проходя по символам будешь увеличивать индекс (вес), т. е. 2 на нулевом месте это 3-ий порт, а 2 на второй позиции это 11-ый порт (3+2^(индекс+1))

sdio ★★★★★ ()
Ответ на: комментарий от sdio

хрень написал, но где-то рядом, лень думать

sdio ★★★★★ ()
#!/bin/sh
VAR="20 80 00 00 00 00 00 00"
SHIFT=0
for i in $VAR
do
        t=$(echo "obase=10;ibase=16;$i" | bc -ql)
        for b in $(seq 1 8)
        do
                x=$(($t >> $b))
                if [ $(($x & 1)) -eq 1 ]; then
                        echo "bit $(($SHIFT + 8 - $b)) is set"
                fi
        done
        SHIFT=$(($SHIFT+8))
done

$ sh snmp.sh bit 3 is set bit 9 is set

anonymous ()
Ответ на: комментарий от anonymous

Спасибо, вроде то что нужно, но работает только с ручным вводом строки :(

decode `snmpwalk -v2c -O vq -c private 10.0.0.2 SNMPv2-SMI::mib-2.17.7.1.4.3.1.2.2`
(standard_in) 1: illegal character: "
не пойму в чем дело. команда возвращает ровно ту же строку «20 08 01 00»

DeeZ ()
Ответ на: комментарий от anonymous

//fix

VAR="20 80 00 00 00 00 00 00"
SHIFT=0
for i in $VAR
do
        t=$(echo "obase=10;ibase=16;$i" | bc -ql)
        x=$t
        for b in $(seq 1 8)
        do
                if [ $(($x & 1)) -eq 1 ]; then
                        echo "bit $(($SHIFT + 9 - $b)) is set"
                fi
                x=$(($t >> $b))
        done
        SHIFT=$(($SHIFT+8))
done
anonymous ()

Добавлю немного индии в тред.

#!/bin/bash
# calculate number of enabled bits in hex data
#for i in `for j in 0 1 2 3 4 5 6 7 8 9 A B C D E F; do         BIN=$(echo "obase=2; ibase=16; $j" | bc );         echo $BIN; done |xargs`  ; do echo $i|grep -o .|grep -c 1 ; done|xargs
#0 1 2 3 4 5 6 7 8 9 A B C D E F
#0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4

function get_bits_count() {
	case $1 in
		"0" )
			echo 0 ;;
		"1" )
			echo 1 ;;
		"2" )
			echo 1 ;;
		"3" )
			echo 2 ;;
		"4" )
			echo 1 ;;
		"5" )
			echo 2 ;;
		"6" )
			echo 2 ;;
		"7" )
			echo 3 ;;
		"8" )
			echo 1 ;;
		"9" )
			echo 2 ;;
		"a" )
			echo 2 ;;
		"A" )
			echo 2 ;;
		"b" )
			echo 3 ;;
		"B" )
			echo 3 ;;
		"c" )
			echo 2 ;;
		"C" )
			echo 2 ;;
		"d" )
			echo 3 ;;
		"D" )
			echo 3 ;;
		"e" )
			echo 3 ;;
		"E" )
			echo 3 ;;
		"f" )
			echo 4 ;;
		"F" )
			echo 4 ;;
		*)
			echo 0 ;;
	esac
}


CNT=0
while read -r -n1 char
do
	CNT=$(( $CNT+`get_bits_count $char` ))
done

echo $CNT

echo "20 08 01 00"|grep -o . | bash ./test.sh
3
echo "20 80 00 00 00 00 00 00 "|grep -o . | bash ./test.sh
2
anonymous ()
Ответ на: комментарий от anonymous

))) Не верно. первый должен был вернуть: 3,13,24
тк: 0010 0000 0000 1000 0000 0001 0000 0000

Всем спасибо. Получилось. Порты ищу так:

members=$(decode "`snmpwalk -v2c -O vq -c private 10.0.0.2 SNMPv2-SMI::mib-2.17.7.1.4.3.1.2.2`")
     for i in   $(seq 1 `expr length $members`)
      do
       let "l= $i - 1"
       if [ ${members:$l:1} = "1" ]
        then
         echo $i
       fi
     done

DeeZ ()

Если именно «посчитать единицы», то:

$ echo -n '0010 0000 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000' | tr -d '0' | tr -d ' ' | wc -c
2
quest ★★★★ ()
Последнее исправление: quest (всего исправлений: 1)
Ответ на: комментарий от DeeZ
awk '{
  while(i = index($0,"1")) {
    print (pos+=i)
    sub(/[^1]*1/,"",$0)
  }
}'
anonymous ()
Ответ на: комментарий от DeeZ
#!/bin/bash

src="20 08 03 00"

echo "$src" | awk '{
  pos=1;
  for(i=1;i<=NF;i++) {
    v=strtonum("0x" $i)
    for(j=7;j>=0;j--) {
      if(rshift(v,j)%2)
        print pos
      pos++;
    }
  }
}'
anonymous ()

bc это ЯП:

echo 'b=2^64; ibase=16; obase=2; a=2080000000000000; while( (b=b/2)>a ) print "0" ; print a, "\n"; ' | bc

0010000010000000000000000000000000000000000000000000000000000000
Если будет нужно больше разрядов, то увеличивать BC_LINE_LENGTH.

mky ★★★★★ ()

Чистый баш без единой доп. утилиты.

#!/bin/bash

TAB=( '' '4' '3' '3 4' '2' '2 4' '2 3' '2 3 4' '1' '1 4' '1 3' '1 3 4' '1 2' '1 2 4' '1 2 3' '1 2 3 4')

INPUT="$1"

i=0
w=0
while [ "${INPUT:$i:1}" ]; do
    sym="${INPUT:$i:1}"
# filter and "convert" input characters
    case $sym in
        "0" )
            ;;
        "1" )
            ;;
        "2" )
            ;;
        "3" )
            ;;
        "4" )
            ;;
        "5" )
            ;;
        "6" )
            ;;
        "7" )
            ;;
        "8" )
            ;;
        "9" )
            ;;
        "a" )
            sym=10;;
        "A" )
            sym=10;;
        "b" )
            sym=11;;
        "B" )
            sym=11;;
        "c" )
            sym=12;;
        "C" )
            sym=12;;
        "d" )
            sym=13 ;;
        "D" )
            sym=13 ;;
        "e" )
            sym=14 ;;
        "E" )
            sym=14 ;;
        "f" )
            sym=15 ;;
        "F" )
            sym=15 ;;
        *)
            sym='-1' ;;
    esac
    i=$(($i+1))
    if [ "$sym" != '-1' ]; then
        LST="${TAB[$sym]}"
        for s in $LST; do
            echo $(($s+$w))
        done
        w=$(($w+4))
    fi
done
./1.sh '20 08 03 00'
3
13
23
24
sdio ★★★★★ ()
Последнее исправление: sdio (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.