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?

sauter
la source
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
Bill Karwin
la source
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.

Keltia
la source
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
pjhobbs
la source
15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff
Orwellophile
la source
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
pjhobbs
la source
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
4

Essayer:

printf "%X\n" ${MY_NUMBER}
Rob Wells
la source
3

Dans zshvous pouvez faire ce genre de chose:

% typeset -i 16 y
% print $(( [#8] x = 32, y = 32 ))
8#40
% print $x $y
8#40 16#20
% setopt c_bases
% print $y
0x20

Exemple tiré de la zshpage de documentation sur l'évaluation arithmétique .

Je pense que Bash a des capacités similaires.

Alastair
la source
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

Daniel Jeznach
la source
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
}
sjas
la source
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
amol s. Patil
la source
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);
    }
CodyChan
la source