Hexadécimal à décimal dans le script Shell

126

Quelqu'un peut-il m'aider à convertir un nombre hexadécimal en nombre décimal dans un script shell?

Par exemple, je veux convertir le nombre hexadécimal en nombre bfca3000décimal à l'aide d'un script shell. Je veux essentiellement la différence de deux nombres hexadécimaux.

Mon code est:

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

Lors de l'exécution, j'obtiens cette erreur:

Line 48: -: syntax error: operand expected (error token is "-")
VenkateshJN
la source
L'inverse: stackoverflow.com/questions/378829/… . Essentiellement les mêmes outils. Et possible duplication
intersite

Réponses:

314

Pour convertir hexadécimal en décimal, il existe de nombreuses façons de le faire dans le shell ou avec un programme externe:

Avec :

$ echo $((16#FF))
255

avec :

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

avec :

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

avec :

$ printf "%d\n" 0xFF
255

avec :

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

avec :

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

avec :

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

avec :

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

avec :

$ groovy -e 'println Integer.parseInt("FF",16)'
255
Gilles Quenot
la source
1
Quelle ? bc est un langage de calcul de précision arbitraire : une commande externe.
Gilles Quenot
10
Et donc ? c'est exactement le but de mes 4 commandes avant de modifier le sens de votre question.
Gilles Quenot
2
La printfsolution est-elle POSIX? Si oui, c'est le meilleur :)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Dans bash, vous pouvez également utiliser $((0xff)), c'est-à-dire avec un préfixe hexadécimal de type C au lieu de 16#, bien que ce N#soit clairement plus général.
Ruslan
3
Le premier exemple bash est sujet à une erreur de dépassement d'entier, par exemple echo $((077E9F2DBF49D100001#FF))dépasse la limite d'entier 64 bits de 2 ^ 64. bcgère cela correctement.
roblogic
39

Gérer une version intégrée très légère de busybox sous Linux signifie que de nombreuses commandes traditionnelles ne sont pas disponibles (bc, printf, dc, perl, python)

echo $((0x2f))
47

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

Merci à Peter Leung pour cette solution.

hinekyle
la source
1
OK, mais méfiez-vous des erreurs de dépassement d'entier, par exemple, le echo $((0x077E9F2DBF49D100001))dépassement de la limite d'entiers 64 bits de 2 ^ 64. bcgère cela correctement
roblogic
13

Une autre façon de le faire en utilisant le shell (bash ou ksh, ne fonctionne pas avec dash):

echo $((16#FF))
255
Tomás Fox
la source
Que signifie le #symbole? Existe-t-il d'autres applications ou documentation pour en savoir plus sur son utilisation?
user1527227
1
Il est mentionné ici: lien . À la fin de la section 6.5, il est dit: "... les nombres prennent la forme [base #] n, où la base facultative est un nombre décimal entre 2 et 64 représentant la base arithmétique, et n est un nombre dans cette base. Si base # est omis, puis base 10 est utilisée. Les chiffres supérieurs à 9 sont représentés par les lettres minuscules, les lettres majuscules, «@» et «_», dans cet ordre. Si la base est inférieure ou égale à 36, Les lettres minuscules et majuscules peuvent être utilisées de manière interchangeable pour représenter des nombres entre 10 et 35. "
Tomás Fox le
11

Différents outils sont à votre disposition à partir d'un shell. Sputnick vous a donné un excellent aperçu de vos options, basé sur votre question initiale. Il mérite certainement des votes pour le temps qu'il a passé à vous donner plusieurs réponses correctes.

Un autre qui ne figure pas sur sa liste:

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

Mais si tout ce que vous voulez faire est de soustraire, pourquoi changer l'entrée en base 10?

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

La dccommande est "desk calc". Il prendra également les entrées de stdin, comme bc, mais au lieu d'utiliser "l'ordre des opérations", il utilise la notation d'empilement ("polonais inversé"). Vous lui donnez des entrées qu'il ajoute à une pile, puis lui donnez des opérateurs qui font sortir les éléments de la pile et repoussez les résultats.

Dans les commandes ci-dessus, nous avons les éléments suivants:

  • 16i- dit à dc d'accepter l'entrée en base 16 (hexadécimal). Ne change pas la base de sortie.
  • BFCA3000 - votre numéro initial
  • 17FF - un nombre hexadécimal aléatoire que j'ai choisi pour soustraire de votre nombre initial
  • - - prenez les deux nombres que nous avons poussés, et soustrayez le dernier du précédent, puis repoussez le résultat dans la pile
  • p- imprimer le dernier élément de la pile. Cela ne change pas la pile, donc ...
  • 10o - dit à dc d'afficher sa sortie en base "10", mais rappelez-vous que notre schéma de numérotation d'entrée est actuellement hexadécimal, donc "10" signifie "16".
  • p - imprimer à nouveau le dernier élément de la pile ... cette fois en hexadécimal.

Vous pouvez construire des solutions mathématiques fabuleusement complexes avec dc. C'est une bonne chose d'avoir dans votre boîte à outils pour les scripts shell.

Ghoti
la source
3

L'erreur telle que signalée apparaît lorsque les variables sont nulles (ou vides):

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

Cela peut se produire car la valeur donnée à bc est incorrecte. Cela pourrait bien être que bc a besoin de valeurs UPPERcase. Il en a besoin BFCA3000, non bfca3000. Cela est facilement corrigé dans bash, utilisez simplement l' ^^extension:

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

Cela changera le script en ceci:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

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

echo "Diference $var5"

Mais il n'est pas nécessaire d'utiliser bc [1], car bash pourrait effectuer la traduction et la soustraction directement:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

echo "Diference $var5"

[1] Remarque: je suppose que les valeurs pourraient être représentées en mathématiques 64 bits, car la différence a été calculée en bash dans votre script d'origine. Bash est limité aux entiers inférieurs à ((2 ** 63) -1) s'il est compilé en 64 bits. Ce sera la seule différence avec bc qui n'a pas une telle limite.


la source
3

Dans le tableau de bord et autres coquilles, vous pouvez utiliser

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

pour convertir un nombre hexadécimal en nombre décimal. Ce n'est pas spécifique à bash ou ksh.

novice
la source
1
Par exempleprintf "%d" 0xff
lashgar