Como adicionar dois números hexadecimais em um script bash

6

Eu quero adicionar duas variáveis hexadecimais em um script bash. Eu quero que eles comecem como hexadecimais e terminem em hexadecimais, não decimais.

O que eu tenho até agora é um pouco sobre um hack. Existe uma solução melhor ou mais elegante?

BASE=0xA000

OFFSET=0x1000

NEW_BASE=$(( $BASE + $OFFSET ))

NEW_BASE='printf "0x%X\n" $NEW_BASE'

echo $NEW_BASE

0xB000
    
por David Aubin 05.01.2018 / 21:45

4 respostas

5

Sim, em bash , printf é a única forma integrada de reformatar um número em uma base diferente e apenas as bases 8, 10 e 16 são suportadas.

Em bash (ao contrário dos shells como ksh93 ou fish ), usar a substituição de comandos implica em bifurcar um subshell. Você pode usar printf -v aqui para evitar o subshell (também disponível nas versões recentes de zsh para print e printf ( print -f ) que também suporta impressão em matrizes):

printf -v NEWBASE '%#X' "$((BASE + OFFSET))"

(em bash , ao contrário de zsh , $((...)) está sujeito à divisão de palavras, por isso é necessário citar para evitar a dependência de $IFS ).

Em zsh , você pode especificar a base de expansão como parte da sintaxe de expansão aritmética (bases 2 a 36):

$ echo $(([#16] 0xff + 0xff))
16#1FE
$ echo $(([##16] 0xff + 0xff))
1FE
$ echo 0x$(([##16] 0xff + 0xff))
0x1FE
$ echo $(([##2] 0xff + 0xff))
111111110

Com ksh e zsh, você também pode forçar a expansão de uma variável inteira para estar em uma base específica com:

typeset -i 16 NEWBASE

A expansão estará no formato 16#1FE . O ksh93 suporta bases até 64, zsh e mksh até 36.

O printf builtin do ksh93 suporta o número de saída em bases arbitrárias, bem como com ou sem o prefixo n# :

$ printf '%..2d\n' 0x1FE
111111110
$ printf '%#..2d\n' 0x1FE
2#111111110

Em ksh93, var=$(printf...) não bifurca um subshell, sendo tão eficiente quanto bash ' printf -v .

    
por 05.01.2018 / 23:44
6

Eu apenas simplificaria seu script como:

printf "0x%X\n" $((0xA000 + 0x1000))
    
por 05.01.2018 / 21:59
2

No GNU ou no moderno BSD dc , você pode fazer assim:

echo A000 1000 | dc -e '16o16i?+p'

16o define a base de saída. 16i define a base de entrada. O ? lê em uma linha da entrada padrão, que nesse caso envia dois números para a pilha. + adiciona-os. p imprime o topo da pilha (a resposta).

    
por 05.01.2018 / 23:51
1

dentro do bash parece ser o bom método. você também pode chamar ferramentas como bc / dc (dependendo das suas preferências) ... eco 'obase = 30; 123456 '| bc

mas eu prefiro o método bash No meu ponto de vista você está indo bem

    
por 05.01.2018 / 21:50