Converte i decimali in esadecimali nello script di shell UNIX


110

In uno script di shell UNIX, cosa posso usare per convertire i numeri decimali in esadecimali? Ho pensato che avrebbe fatto il trucco, ma non sto realizzando che gli sto alimentando rappresentazioni ASCII di numeri.

printf? Schifoso! Lo sto usando per ora, ma cos'altro è disponibile?


8
Devo chiedere, cosa c'è di schifo in printf? Molti linguaggi di programmazione comuni supportano la formattazione simile a printf, quindi le soluzioni printf seguenti sarebbero sicuramente le più facili da capire per gli sviluppatori.
Michael Scheper

4
Ragazzi, non lo so - è stato cinque anni fa! Penso che forse ho pensato che non fosse vero guscio o qualcosa del genere.
skiphoppy

Risposte:


108
echo "obase=16; 34" | bc

Se vuoi filtrare un intero file di numeri interi, uno per riga:

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

1
Ho guardato sia bc (1) che dc (1) e ho perso quello.
Keltia

3
@skiphoppy: se scrivi: echo "obase = 16; 12 34 56" | bc ottieni 1E240, proprio come se avessi scritto: echo "obase = 16; 123456" | avanti Cristo. Quindi il modo per gestire numeri arbitrari di interi su una riga è mettere ogni numero su una riga separata: tr '' '\ 015' <input | bc (mappa gli spazi vuoti in nuove righe).
Jonathan Leffler

1
Questo è fantastico se ti capita di avere 'bc', ma 'printf' fa parte di bash stesso
fuzzyTew

1
@ Bill Karwin, o zsh, o busybox, ma forse non qualche shell che non ho provato? Non tengo più installato plain sh ma chiaramente skiphoppy sta cercando quali altre opzioni ci sono
fuzzyTew

2
@ Sridhar-Sarnobat, questo è decimale in esadecimale. Presumo che tu intenda convertire l'esagono in dec. Per farlo, imposta ibase=16. Ti potrebbe piacere leggere il manuale su bc per maggiori dettagli.
Bill Karwin

186

Provato printf(1)?

printf "%x\n" 34
22

Probabilmente ci sono modi per farlo con le funzioni incorporate in tutte le shell, ma sarebbe meno portabile. Non ho controllato le specifiche di POSIX sh per vedere se ha tali capacità.


5
Non c'è molto più POSIX di printf. Funziona anche in "sh".
Orwellophile

4
printf non è una precisione arbitraria. bcè. per esempio, prendendo 238862874857408875879219909679752457540come input, printf ci dà "Risultato troppo grande". il metodo BC funziona alla grande per cose più grandi di un int / long / bigint standard
Andrew Backer

3
E, se vuoi lettere maiuscole in esadecimale, printf "%X"
usale

3
E per forzare un output come "0x00", puoi utilizzare printf "0x% 02X"
gbetous

1
... e bcnon è disponibile ovunque (almeno non sul mio Linux incorporato).
Matthieu

69

Da esadecimale a decimale:

$ echo $((0xfee10000))
4276158464

Da decimale a esadecimale:

$ 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 VARè un'estensione bash. Non menzionato nella pagina man , rivelato solo se si chiama printfsenza argomenti
Adrian W

5

Scusa colpa mia, prova questo ...

#!/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}"

Esempio:

$ ./dtoh 1024
400

1
Grazie questo ha aiutato molto per env. dove printfe i hexcomandi non sono disponibili.
benchuk

2
@benchuk dove printfnon è disponibile?
Matthieu



2

Nel mio caso, mi sono imbattuto in un problema con l'utilizzo della soluzione printf:

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

Il modo più semplice era usare la soluzione con bc , suggerita nel post più alto:

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


Cosa aggiunge la tua soluzione a quelle scritte anni prima?
Matthieu

1
@ Matthieu Menziona la questione dei numeri con zeri iniziali, che Bash printf interpreta inutilmente come ottale, e dimostra una soluzione che evita il problema.
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

Questo non è uno script di shell, ma è lo strumento cli che sto usando per convertire i numeri tra 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);
    }
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.