Hexadecimal para decimal em shell script


126

Alguém pode me ajudar a converter um número hexadecimal em número decimal em um script de shell?

Por exemplo, eu quero converter o número hexadecimal bfca3000em decimal usando um script de shell. Eu basicamente quero a diferença de dois números hexadecimais.

Meu código é:

var3=`echo "ibase=16; $var1" | bc`
var4=`echo "ibase=16; $var2" | bc`
var5=$(($var4-$var3))               # [Line 48]

Ao executar, recebo este erro:

Line 48: -: syntax error: operand expected (error token is "-")

O contrário: stackoverflow.com/questions/378829/… . Essencialmente as mesmas ferramentas. E possível duplicação de site cruzado de: superuser.com/questions/226163/…
— Ciro Santilli, em

Respostas:


314

Para converter de hex para decimal, há muitas maneiras de fazer isso no shell ou com um programa externo:

Com :

$ echo $((16#FF))
255

com :

$ echo "ibase=16; FF" | bc
255

com :

$ perl -le 'print hex("FF");'
255

com :

$ printf "%d\n" 0xFF
255

com :

$ python -c 'print(int("FF", 16))'
255

com :

$ ruby -e 'p "FF".to_i(16)'
255

com :

$ nodejs <<< "console.log(parseInt('FF', 16))"
255

com :

$ rhino<<EOF
print(parseInt('FF', 16))
EOF
...
255

com :

$ groovy -e 'println Integer.parseInt("FF",16)'
255

1
O que ? bc é uma linguagem arbitrária da calculadora de precisão : um comando externo.
— Gilles Quenot

10
E entao ? esse é exatamente o objetivo dos meus 4 comandos antes de modificar o sentido da sua pergunta.
— Gilles Quenot

2
A printfsolução é POSIX? Se sim, é o melhor :)
— Ciro Santilli郝海东冠状病六四事件法轮功

3
No bash, você também pode usar $((0xff)), ou seja, com prefixo hexadecimal do tipo C em vez de 16#, embora N#seja claramente mais geral.
— Ruslan #

3
O primeiro exemplo do bash é suscetível a erro de excesso de número inteiro, por exemplo, echo $((077E9F2DBF49D100001#FF))excede o limite inteiro de 64 bits de 2 ^ 64. bclida com isso corretamente.
— roblogic

39

Lidar com uma versão incorporada muito leve do busybox no Linux significa que muitos dos comandos tradicionais não estão disponíveis (bc, printf, dc, perl, python)

echo $((0x2f))
47

hexNum=2f
echo $((0x${hexNum}))
47

Agradecemos a Peter Leung por esta solução.


1
OK, mas cuidado com o erro de número inteiro excedido, por exemplo, echo $((0x077E9F2DBF49D100001))excede o limite inteiro de 64 biit de 2 ^ 64. bclida com isso corretamente
— roblogic

13

Mais uma maneira de fazer isso usando o shell (bash ou ksh, não funciona com o dash):

echo $((16#FF))
255

O que significa o #símbolo? Existem outros aplicativos ou documentação para ler mais sobre seu uso?
— User1527227

1
É mencionado aqui: link . No final da seção 6.5, diz: "... os números assumem a forma [base #] n, onde a base opcional é um número decimal entre 2 e 64 representando a base aritmética, e n é um número nessa base. Se omissão da base # é omitida, a base 10. é usada. Os dígitos maiores que 9 são representados pelas letras minúsculas, maiúsculas '@' e '_', nessa ordem. Se a base for menor ou igual a 36, letras minúsculas e maiúsculas podem ser usadas de forma intercambiável para representar números entre 10 e 35. "
— Tomás Fox

11

Várias ferramentas estão disponíveis para você a partir de um shell. Sputnick lhe deu uma excelente visão geral de suas opções, com base em sua pergunta inicial. Ele definitivamente merece votos pelo tempo que passou dando a você várias respostas corretas.

Mais um que não está na lista dele:

[ghoti@pc ~]$ dc -e '16i BFCA3000 p'
3217698816

Mas se tudo o que você quer fazer é subtrair, por que se preocupar em mudar a entrada para a base 10?

[ghoti@pc ~]$ dc -e '16i BFCA3000 17FF - p 10o p'
3217692673
BFCA1801
[ghoti@pc ~]$ 

O dccomando é "desk calc". Ele também recebe a entrada do stdin, como bc, mas em vez de usar a "ordem das operações", ele usa a notação de empilhamento ("polonês reverso"). Você fornece as entradas que adiciona a uma pilha, depois os operadores que retiram itens da pilha e pressionam os resultados.

Nos comandos acima, temos o seguinte:

  • 16i- diz ao dc para aceitar a entrada na base 16 (hexadecimal). Não altera a base de saída.
  • BFCA3000 - seu número inicial
  • 17FF - um número hexadecimal aleatório que escolhi para subtrair do seu número inicial
  • - - pegue os dois números que pressionamos e subtraia o último do anterior, depois empurre o resultado de volta para a pilha
  • p- imprima o último item na pilha. Isso não muda a pilha, então ...
  • 10o - diz ao dc para imprimir sua saída na base "10", mas lembre-se de que nosso esquema de numeração de entrada é atualmente hexadecimal, portanto "10" significa "16".
  • p - imprima o último item na pilha novamente ... desta vez em hexadecimal.

Você pode construir soluções matemáticas fabulosamente complexas com dc. É bom ter em sua caixa de ferramentas para scripts de shell.


3

O erro conforme relatado aparece quando as variáveis ​​são nulas (ou vazias):

$ unset var3 var4; var5=$(($var4-$var3))
bash: -: syntax error: operand expected (error token is "-")

Isso poderia acontecer porque o valor dado a bc estava incorreto. Pode ser que o bc precise de valores UPPERcase. Precisa BFCA3000, não bfca3000. Isso é facilmente corrigido no bash, basta usar a ^^expansão:

var3=bfca3000; var3=`echo "ibase=16; ${var1^^}" | bc`

Isso mudará o script para isso:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

var3="$(echo "ibase=16; ${var1^^}" | bc)"
var4="$(echo "ibase=16; ${var2^^}" | bc)"

var5="$(($var4-$var3))"

echo "Diference $var5"

Mas não há necessidade de usar bc [1], pois o bash poderia executar a tradução e a subação diretamente:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

var5="$(( 16#$var2 - 16#$var1 ))"

echo "Diference $var5"

[1] Nota: Estou assumindo que os valores possam ser representados na matemática de 64 bits, pois a diferença foi calculada no bash no seu script original. Bash é limitado a números inteiros menores que ((2 ** 63) -1) se compilados em 64 bits. Essa será a única diferença com bc que não possui esse limite.


3

No traço e outras conchas, você pode usar

printf "%d\n" (your hexadecimal number)

para converter um número hexadecimal em decimal. Isso não é específico do bash ou do ksh.


1
por exemploprintf "%d" 0xff
— lashgar
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.