Da esadecimale a decimale in Shell Script


126

Qualcuno può aiutarmi a convertire un numero esadecimale in numero decimale in uno script di shell?

Ad esempio, voglio convertire il numero esadecimale bfca3000in decimale usando uno script di shell. In pratica voglio la differenza di due numeri esadecimali.

Il mio codice è:

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

Durante l'esecuzione, ottengo questo errore:

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

Al contrario: stackoverflow.com/questions/378829/… . Essenzialmente gli stessi strumenti. E possibile duplicato cross site di: superuser.com/questions/226163/…
Ciro Santilli 12 冠状 病 六四 事件 法轮功

Risposte:


314

Per convertire da esadecimale a decimale, ci sono molti modi per farlo nella shell o con un programma esterno:

Con :

$ echo $((16#FF))
255

con :

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

con :

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

con :

$ printf "%d\n" 0xFF
255

con :

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

con :

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

con :

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

con :

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

con :

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

1
Che cosa ? bc è un linguaggio di calcolatrice di precisione arbitrario : un comando esterno.
Gilles Quenot

10
E così ? questo è esattamente lo scopo dei miei 4 comandi prima di modificare il senso della tua domanda.
Gilles Quenot

2
La printfsoluzione è POSIX? Se sì, è il migliore :)
Ciro Santilli 5 冠状 病 六四 事件 法轮功

3
In bash puoi anche usare $((0xff)), cioè con prefisso esadecimale di tipo C invece di 16#, sebbene N#sia chiaramente più generale.
Ruslan,

3
Il primo esempio bash è suscettibile all'errore di overflow dei numeri interi, ad esempio echo $((077E9F2DBF49D100001#FF))overflow del limite intero a 64 bit di 2 ^ 64. bcgestisce questo correttamente.
roblogic

39

Trattare con una versione incorporata molto leggera di busybox su Linux significa che molti dei comandi tradizionali non sono disponibili (bc, printf, dc, perl, python)

echo $((0x2f))
47

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

Ringraziamo Peter Leung per questa soluzione.


1
OK ma attenzione all'errore di overflow dei numeri interi, ad es. echo $((0x077E9F2DBF49D100001))Overflow del limite intero a 64 bit di 2 ^ 64. bcgestisce questo in modo adeguato
roblogic

13

Un altro modo per farlo usando la shell (bash o ksh, non funziona con dash):

echo $((16#FF))
255

Cosa significa il #simbolo? Ci sono altre applicazioni o documentazione per saperne di più sul suo utilizzo?
user1527227

1
È menzionato qui: link . Alla fine della sezione 6.5 si dice: "... i numeri assumono la forma [base #] n, dove la base opzionale è un numero decimale compreso tra 2 e 64 che rappresenta la base aritmetica e n è un numero in quella base. Se la base # viene omessa, quindi viene utilizzata la base 10. Le cifre maggiori di 9 sono rappresentate dalle lettere minuscole, le lettere maiuscole, "@" e "_", in questo ordine. Se la base è inferiore o uguale a 36, le lettere minuscole e maiuscole possono essere utilizzate in modo intercambiabile per rappresentare numeri compresi tra 10 e 35. "
Tomás Fox,

11

All'interno di una shell sono disponibili vari strumenti. Sputnick ti ha fornito un'eccellente panoramica delle tue opzioni, in base alla tua domanda iniziale. Merita sicuramente i voti per il tempo che ha trascorso dandoti più risposte corrette.

Un altro che non è nella sua lista:

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

Ma se tutto ciò che vuoi fare è sottrarre, perché preoccuparsi di cambiare l'ingresso in base 10?

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

Il dccomando è "desk calc". Prenderà anche input da stdin, come bc, ma invece di usare "ordine delle operazioni", usa la notazione di sovrapposizione ("inversione polacca"). Gli dai input che aggiunge a uno stack, quindi gli operatori che estraggono gli articoli dallo stack e spingono indietro sui risultati.

Nei comandi sopra abbiamo il seguente:

  • 16i- dice a cc di accettare l'input nella base 16 (esadecimale). Non cambia la base di output.
  • BFCA3000 - il tuo numero iniziale
  • 17FF - un numero esadecimale casuale che ho scelto per sottrarre dal tuo numero iniziale
  • - - prendi i due numeri che abbiamo premuto e sottrai il successivo dal precedente, quindi rimetti il ​​risultato in pila
  • p- stampa l'ultimo oggetto in pila. Questo non cambia lo stack, quindi ...
  • 10o - dice a dc di stampare il suo output nella base "10", ma ricorda che il nostro schema di numerazione degli input è attualmente esadecimale, quindi "10" significa "16".
  • p - stampa di nuovo l'ultimo oggetto in pila ... questa volta in esadecimale.

Puoi costruire soluzioni matematiche incredibilmente complesse con dc. È una buona cosa avere nella tua cassetta degli attrezzi per gli script di shell.


3

L'errore come riportato appare quando le variabili sono null (o vuote):

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

Ciò potrebbe accadere perché il valore fornito a bc non era corretto. Potrebbe essere che bc abbia bisogno di valori UPPERcase. Ha bisogno BFCA3000, no bfca3000. Ciò è facilmente risolvibile in bash, basta usare l' ^^espansione:

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

Questo cambierà lo script in questo:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

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

echo "Diference $var5"

Ma non è necessario utilizzare bc [1], poiché bash potrebbe eseguire direttamente la traduzione e la sottostrazione:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

echo "Diference $var5"

[1] Nota: suppongo che i valori possano essere rappresentati in matematica a 64 bit, poiché la differenza è stata calcolata in bash nello script originale. Bash è limitato a numeri interi inferiori a ((2 ** 63) -1) se compilato in 64 bit. Questa sarà l'unica differenza con bc che non ha tale limite.


3

In dash e altre shell, è possibile utilizzare

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

per convertire un numero esadecimale in decimale. Questo non è bash, o ksh, specifico.


1
es.printf "%d" 0xff
lashgar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.