Como canalizar e converter o primeiro campo de decimal para hex

1

Eu tenho a seguinte saída na tela

170.170.170.0.156.96 24

que eu gostaria de canalizar & converter para o seguinte formato

b8:27:eb:ef:3b:4a 24

em essência, é um decimal para hex conversão do primeiro campo, pelo que os pontos são substituídos por dois pontos. Alguma sugestão?

    
por R4C3R 02.02.2018 / 17:49

8 respostas

2

$ cat input
170.170.170.0.156.96 24
$ perl -lane '$F[0] =~ s/(\d+)/sprintf "%02x",$1/eg; $F[0] =~ tr/./:/; print "@F"' < input
aa:aa:aa:00:9c:60 24
$ 

Repetir a entrada padrão não imprimindo com uma divisão em @F , mangle a primeira coluna ( $F[0] ) substituindo todas as execuções de dígitos pelo seu equivalente hexadecimal mais o. para: tr anslation. Imprima os novos valores contidos em @F .

    
por 02.02.2018 / 18:14
1

Python abordagens:

- usando re module:

python -c 'import sys,re;
print(re.sub(r"\d+(?!$)", lambda m: "{:x}".format(int(m.group())), 
sys.stdin.read().strip()))' <inputfile

- usando split() + map() + join() chain:

python -c 'import sys; parts=sys.stdin.read().strip().split(); 
print(".".join(map(lambda n: "{:x}".format(int(n)), parts[0].split("."))) 
 + " " + parts[1])' <inputfile

A saída (para ambas as abordagens):

aa.aa.aa.0.9c.60 24
    
por 02.02.2018 / 19:16
1

Usando awk e tratando os pontos como separadores de registro:

echo '170.170.170.0.156.96 24' |
awk -v RS='.' '{ s = (s ? s ":" : "" ) sprintf("%02x", $0) } END { print s }'

Aqui, a string resultante s é construída a partir da conversão dos inteiros decimais em hexadecimais usando sprintf() . No final da entrada, o resultado é impresso.

Observe que o 24 à direita é descartado na conversão decimal para hexadecimal, portanto, nenhum tratamento explícito é necessário.

O resultado do pipeline acima é a string aa:aa:aa:00:9c:60 .

    
por 03.02.2018 / 10:17
0

Aqui está uma solução com awk :

$ awk -F. \
 '{for(i=1; i<6; i++){printf "%02x:", $i}\
 {  printf "%02x ", $6 }printf substr($6, length($6)-1, length($6))"\n"}' inputfile

Faz um loop nos primeiros 5 campos separados por . , imprime a conversão hexadecimal com : e, em seguida, a 6ª sem : . Em seguida, separa 24 do 6º campo imprimindo dois últimos caracteres.

    
por 02.02.2018 / 18:46
0

Para processar a parte do endereço IP, podemos tirar proveito de IFS e divisão de palavras em subshell (portanto, sem coalho $var ) e da capacidade de printf de processar argumentos de tamanho variável para caber na string de formato.

$ ( IFS='.';var='170.170.170.0.156.96';new=$(printf '%02x:' $var); echo ${new:0:${#new}-1} )
aa:aa:aa:00:9c:60

Também vale a pena notar que ${new:0:${#new}-1} é usado para cortar o último caractere : cegamente adicionado por printf .

Considerando que 170.170.170.0.156.96 24 pode vir como uma única sequência de entrada em stdin , poderíamos ler os dois em variáveis e processar separadamente:

$ echo "170.170.170.0.156.96 24" | while read ip num ;  do
> hex=$( IFS='.';new=$(printf '%02x:' $ip); echo ${new:0:${#new}-1} );  
> printf '%s %d\n' "$hex" "$num"; done
aa:aa:aa:00:9c:60 24

Se você também precisar fazer uso da saída posteriormente no script, considere gravar o valor resultante em pipe nomeado, continuar trabalhando na mesma subzela ou usando a substituição de processo. Veja este para mais informações.

    
por 02.02.2018 / 23:22
0

Outra awk solution

$ awk -F. <inputfile \
'{for(i=1;i<7;i++){printf"%02x%c",$i,i<6?":":" "};print gensub(/.* /,"",$6)}'

Ou na forma mais simples

$ awk -F. <inputfile \
'{printf"%02x:%02x:%02x:%02x:%02x:%02x %s",$1,$2,$3,$4,$5,$6,gensub(/^.* /,"",$6)}'

Combinação shell / awk. Depende de como o shell printf felizmente continua usando o mesmo padrão para vários argumentos.

$ echo $A
170.170.170.0.156.96 24
$ printf "%02x:" ${A//./ }|awk -F'....$' -vc="${A#* }" '{print $1,c}'
aa:aa:aa:00:9c:60 24
$
    
por 02.02.2018 / 22:56
0

Com sed (GNU sed) 4.4

echo '170.170.170.0.156.96 24' | 
sed 'h;s/ .*//;s/\./ /g;s/^/printf "%02x:" /e;x;s/[^ ]* //;x;G;s/:\n/ /'
    
por 03.02.2018 / 20:09
0

Um awk complicado:

$ cat file1
170.170.170.0.156.96 24
170.170.170.0.156.96 28

$ awk '{printf "%x%s",$0,RT=="."?":":RT}' RS="[. ]|\n" file1
aa:aa:aa:0:9c:60 18
aa:aa:aa:0:9c:60 1c
    
por 02.02.2018 / 22:34