bash - Hexadecimal a decimal en Shell Script
(6)
El error como se muestra aparece cuando las variables son nulas (o vacías):
$ unset var3 var4; var5=$(($var4-$var3))
bash: -: syntax error: operand expected (error token is "-")
Eso podría suceder porque el valor dado a bc era incorrecto. Eso bien podría ser que bc necesite MAYORES valores de caso. Necesita BFCA3000
, no bfca3000
. Eso se soluciona fácilmente en bash, solo usa la expansión ^^
:
var3=bfca3000; var3=`echo "ibase=16; ${var1^^}" | bc`
Eso cambiará la secuencia de comandos a esto:
#!/bin/bash
var1="bfca3000"
var2="efca3250"
var3="$(echo "ibase=16; ${var1^^}" | bc)"
var4="$(echo "ibase=16; ${var2^^}" | bc)"
var5="$(($var4-$var3))"
echo "Diference $var5"
Pero no es necesario usar bc [1], ya que bash podría realizar la traducción y la substracción directamente:
#!/bin/bash
var1="bfca3000"
var2="efca3250"
var5="$(( 16#$var2 - 16#$var1 ))"
echo "Diference $var5"
[1] Nota: Supongo que los valores se pueden representar en matemática de 64 bits, ya que la diferencia se calculó en bash en el guión original. Bash está limitado a enteros menores que ((2 ** 63) -1) si se compila en 64 bits. Esa será la única diferencia con bc que no tiene ese límite.
¿Alguien puede ayudarme a decir cómo convertir un número hexadecimal a un número decimal en un script de shell? Por ejemplo, quiero convertir el número hexadecimal bfca3000
a decimal usando un script de shell. Básicamente quiero la diferencia de dos números hexadecimales. Mi código es:
var3=`echo "ibase=16; $var1" | bc`
var4=`echo "ibase=16; $var2" | bc`
var5=$(($var4-$var3)) # [Line 48]
Al ejecutar, recibo el error como:
Line 48: -: syntax error: operand expected (error token is "-")
En el tablero y otras conchas, puedes usar
printf "%d/n" (your hexadecimal number)
para convertir un número hexadecimal a decimal. Esto no es bash, o ksh, específico.
Para convertir hex2dec, estas son muchas maneras de hacerlo en un shell o script:
Con bash (cuidado con los espacios en blanco):
$ echo $(( 16#FF ))
255
con bc :
$ echo "ibase=16; FF" | bc
255
con perl :
$ perl -le ''print hex("FF");''
255
con printf :
$ printf "%d/n" 0xFF
255
con python :
$ python -c ''print(int("FF", 16))''
255
con ruby :
$ ruby<<EOF
p "FF".to_i(16).to_s(10)
EOF
"255"
con node.js :
$ nodejs <<< "console.log(parseInt(''FF'', 16))"
255
con rhino :
$ rhino<<EOF
print(parseInt(''FF'', 16))
EOF
...
255
con groovy :
$ groovy -e ''println Integer.parseInt("FF",16)''
255
Tratar con una versión incrustada muy ligera de busybox en Linux significa que muchos de los comandos tradicionales no están disponibles (bc, printf, dc, perl, python)
echo $((0x2f))
47
hexNum=2f
echo $((0x${hexNum}))
47
Gracias a Peter Leung por esta solución.
Una forma más de hacerlo usando el shell (bash o ksh, no funciona con el guión):
echo $((16#FF))
255
Varias herramientas están disponibles para usted desde dentro de un caparazón. Sputnick le ha dado una excelente descripción de sus opciones, basada en su pregunta inicial. Definitivamente merece los votos por el tiempo que pasó brindándole múltiples respuestas correctas.
Una más que no está en su lista:
[ghoti@pc ~]$ dc -e ''16i BFCA3000 p''
3217698816
Pero si todo lo que quiere hacer es restar, ¿por qué molestarse en cambiar la entrada a la base 10?
[ghoti@pc ~]$ dc -e ''16i BFCA3000 17FF - p 10o p''
3217692673
BFCA1801
[ghoti@pc ~]$
El comando dc
es "desk calc". También tomará la entrada de stdin, como bc
, pero en lugar de usar "orden de operaciones", usa la notación de apilamiento ("polaco inverso"). Le das las entradas que agrega a una pila, luego le das operadores que sacan elementos de la pila, y vuelves a presionar los resultados.
En los comandos anteriores, tenemos lo siguiente:
-
16i
- le dice a dc que acepte la entrada en la base 16 (hexadecimal). No cambia la base de salida. -
BFCA3000
: tu número inicial -
17FF
- un número hexadecimal al azar que elegí para restar de tu número inicial -
-
- toma los dos números que hemos presionado, y reste el último del anterior, luego inserta el resultado en la pila -
p
: imprime el último elemento en la pila. Esto no cambia la pila, entonces ... -
10o
- le dice a dc que imprima su salida en la base "10", pero recuerde que nuestro esquema de numeración de entrada es actualmente hexadecimal, entonces "10" significa "16". -
p
- imprime el último elemento en la pila de nuevo ... esta vez en hexadecimal.
Puede construir soluciones matemáticas fabulosamente complejas con dc. Es bueno tener en su caja de herramientas scripts de shell.