Conversion décimale en hexadécimal dans un script shell UNIX


110

Dans un script shell UNIX, que puis-je utiliser pour convertir des nombres décimaux en hexadécimal? Je pensais qu'od ferait l'affaire, mais je ne réalise pas que je lui donne des représentations ASCII de nombres.

printf? Brut! Vous l'utilisez pour le moment, mais qu'est-ce qui est disponible?


8
Je dois demander, qu'est-ce qui est dégoûtant à propos de printf? De nombreux langages de programmation courants prennent en charge le formatage de type printf, de sorte que les solutions printf ci-dessous seraient certainement les plus faciles à comprendre pour les développeurs.
Michael Scheper

4
Garçon, je ne sais pas - c'était il y a cinq ans! Je pense que je pensais peut-être que ce n'était pas une vraie coquille ou quelque chose comme ça.
skiphoppy

Réponses:


108
echo "obase=16; 34" | bc

Si vous souhaitez filtrer un fichier entier d'entiers, un par ligne:

( echo "obase=16" ; cat file_of_integers ) | bc

1
J'ai regardé à la fois bc (1) et dc (1) et j'ai raté celui-là.
Keltia

3
@skiphoppy: Si vous écrivez: echo "obase = 16; 12 34 56" | bc vous obtenez 1E240, exactement comme si vous aviez écrit: echo "obase = 16; 123456" | avant JC. Donc, la façon de traiter des nombres arbitraires d'entiers sur une seule ligne est de mettre chaque nombre sur sa propre ligne: tr '' '\ 015' <input | bc (mapper les blancs aux nouvelles lignes).
Jonathan Leffler

1
C'est génial si vous avez 'bc', mais 'printf' fait partie de bash lui
fuzzyTew

1
@Bill Karwin, ou zsh, ou busybox, mais peut-être pas un shell que je n'ai pas essayé? Je ne garde plus le sh plain installé, mais skiphoppy recherche clairement les autres options disponibles
fuzzyTew

2
@ Sridhar-Sarnobat, c'est décimal à hexadécimal. Je suppose que vous voulez dire convertir hexadécimal en déc. Pour ce faire, définissez ibase=16. Vous voudrez peut-être lire le manuel sur bc pour plus de détails.
Bill Karwin

186

Essayé printf(1)?

printf "%x\n" 34
22

Il existe probablement des moyens de le faire avec des fonctions intégrées dans tous les shells, mais ce serait moins portable. Je n'ai pas vérifié les spécifications POSIX sh pour voir s'il a de telles capacités.


5
Il ne reçoit pas beaucoup plus de POSIX que printf. Cela fonctionne même dans "sh".
Orwellophile

4
printf n'est pas une précision aribtraire. bcest. par exemple, en prenant 238862874857408875879219909679752457540comme entrée, printf nous donne "Résultat trop grand". la méthode BC fonctionne très bien pour les choses plus grandes qu'un int / long / bigint standard
Andrew Backer

3
Et, si vous voulez des lettres majuscules en hexadécimal, utilisez printf "%X"avec X majuscule.
andrybak

3
Et pour forcer une sortie comme "0x00", vous pouvez utiliser printf "0x% 02X"
gbetous

1
... et bcn'est pas disponible partout (du moins pas sur mon Linux embarqué).
Matthieu

69

Hexidécimal à décimal:

$ echo $((0xfee10000))
4276158464

Décimal à hexadécimal:

$ printf '%x\n' 26
1a

15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff

1
-v VARest une extension bash. Non mentionné dans la page de manuel , révélé uniquement si on appelle printfsans arguments
Adrian W

5

Désolé de ma faute, essayez ceci ...

#!/bin/bash
:

declare -r HEX_DIGITS="0123456789ABCDEF"

dec_value=$1
hex_value=""

until [ $dec_value == 0 ]; do

    rem_value=$((dec_value % 16))
    dec_value=$((dec_value / 16))

    hex_digit=${HEX_DIGITS:$rem_value:1}

    hex_value="${hex_digit}${hex_value}"

done

echo -e "${hex_value}"

Exemple:

$ ./dtoh 1024
400

1
Merci, cela a beaucoup aidé pour env. où printfet les hexcommandes ne sont pas disponibles.
benchuk

2
@benchuk où n'est printfpas disponible?
Matthieu



2

Dans mon cas, je suis tombé sur un problème avec l'utilisation de la solution printf:

$ printf "%x" 008 bash: printf: 008: invalid octal number

Le moyen le plus simple était d'utiliser la solution avec bc , suggérée dans l'article supérieur:

$ bc <<< "obase=16; 008" 8


Qu'est-ce que votre solution ajoute à celles écrites des années auparavant?
Matthieu

1
@Matthieu Il mentionne le problème des nombres avec des zéros non significatifs, que Bash printf interprète inutilement comme octal, et démontre une solution qui évite le problème.
mwfearnley

2
xd() {
    printf "hex> "
    while read i
    do
        printf "dec  $(( 0x${i} ))\n\nhex> "
    done
}
dx() {
    printf "dec> "
    while read i
    do
        printf 'hex  %x\n\ndec> ' $i
    done
}

1
# number conversion.

while `test $ans='y'`
do
    echo "Menu"
    echo "1.Decimal to Hexadecimal"
    echo "2.Decimal to Octal"
    echo "3.Hexadecimal to Binary"
    echo "4.Octal to Binary"
    echo "5.Hexadecimal to  Octal"
    echo "6.Octal to Hexadecimal"
    echo "7.Exit"

    read choice
    case $choice in

        1) echo "Enter the decimal no."
           read n
           hex=`echo "ibase=10;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        2) echo "Enter the decimal no."
           read n
           oct=`echo "ibase=10;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        3) echo "Enter the hexadecimal no."
           read n
           binary=`echo "ibase=16;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        4) echo "Enter the octal no."
           read n
           binary=`echo "ibase=8;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        5) echo "Enter the hexadecimal no."
           read n
           oct=`echo "ibase=16;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        6) echo "Enter the octal no."
           read n
           hex=`echo "ibase=8;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        7) exit 
        ;;
        *) echo "invalid no." 
        ;;

    esac
done

1

Ce n'est pas un script shell, mais c'est l'outil cli que j'utilise pour convertir des nombres entre bin / oct / dec / hex:

    #!/usr/bin/perl

    if (@ARGV < 2) {
      printf("Convert numbers among bin/oct/dec/hex\n");
      printf("\nUsage: base b/o/d/x num num2 ... \n");
      exit;
    }

    for ($i=1; $i<@ARGV; $i++) {
      if ($ARGV[0] eq "b") {
                    $num = oct("0b$ARGV[$i]");
      } elsif ($ARGV[0] eq "o") {
                    $num = oct($ARGV[$i]);
      } elsif ($ARGV[0] eq "d") {
                    $num = $ARGV[$i];
      } elsif ($ARGV[0] eq "h") {
                    $num = hex($ARGV[$i]);
      } else {
                    printf("Usage: base b/o/d/x num num2 ... \n");
                    exit;
      }
      printf("0x%x = 0d%d = 0%o = 0b%b\n", $num, $num, $num, $num);
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.