Konvertieren Sie Dezimalstellen in Hexadezimalzahlen in UNIX-Shell-Skripten

110

Was kann ich in einem UNIX-Shell-Skript verwenden, um Dezimalzahlen in Hexadezimalzahlen umzuwandeln? Ich dachte, od würde den Trick machen, aber es ist nicht klar, dass ich es mit ASCII-Darstellungen von Zahlen füttere.

printf? Brutto! Verwenden Sie es jetzt, aber was ist noch verfügbar?

Skiphoppy
quelle
8
Ich muss fragen, was ist eklig an printf? Viele gängige Programmiersprachen unterstützen die printf-ähnliche Formatierung, daher sind die folgenden printf-Lösungen für Entwickler sicherlich am einfachsten zu verstehen.
Michael Scheper
4
Junge, ich weiß nicht - das war vor fünf Jahren! Ich denke, vielleicht dachte ich, es wäre keine echte Hülle oder so.
Skiphoppy

Antworten:

108
echo "obase=16; 34" | bc

Wenn Sie eine ganze Datei mit ganzen Zahlen filtern möchten, eine pro Zeile:

( echo "obase=16" ; cat file_of_integers ) | bc
Bill Karwin
quelle
1
Ich habe sowohl bc (1) als auch dc (1) angeschaut und diesen verpasst.
Keltia
3
@skiphoppy: Wenn Sie schreiben: echo "obase = 16; 12 34 56" | bc Sie erhalten 1E240, genauso wie Sie geschrieben haben: echo "obase = 16; 123456" | bc. Der Weg, um mit einer beliebigen Anzahl von Ganzzahlen in einer Zeile umzugehen, besteht darin, jede Zahl in eine eigene Zeile zu setzen: tr '' '\ 015' <input | bc (Kartenrohlinge zu Zeilenumbrüchen).
Jonathan Leffler
1
Dies ist großartig, wenn Sie zufällig 'bc' haben, aber 'printf' Teil von bash selbst ist
fuzzyTew
1
@ Bill Karwin oder zsh oder Busybox, aber vielleicht keine Shell, die ich nicht ausprobiert habe? Ich halte nicht mehr einfach sh installiert, aber Skiphoppy sucht eindeutig nach anderen Optionen
fuzzyTew
2
@ Sridhar-Sarnobat, dies ist dezimal bis hexadezimal. Ich nehme an, Sie meinen Hex in Dez konvertieren. Stellen Sie dazu ein ibase=16. Vielleicht möchten Sie das Handbuch auf bc für weitere Details lesen .
Bill Karwin
186

Versucht printf(1)?

printf "%x\n" 34
22

Es gibt wahrscheinlich Möglichkeiten, dies mit eingebauten Funktionen in allen Shells zu tun, aber es wäre weniger portabel. Ich habe die POSIX sh-Spezifikationen nicht überprüft, um festzustellen, ob sie über solche Funktionen verfügen.

Keltia
quelle
5
Es gibt nicht viel mehr POSIX als printf. Dies funktioniert sogar in "sh".
Orwellophile
4
printf ist keine willkürliche Präzision. bcist. Wenn Sie beispielsweise 238862874857408875879219909679752457540printf als Eingabe verwenden, erhalten Sie "Ergebnis zu groß". Die BC-Methode eignet sich hervorragend für Dinge, die größer als ein Standard-Int / Long / Bigint sind
Andrew Backer
3
Und wenn Sie Großbuchstaben in printf "%X"
hexadezimaler Schreibweise
3
Und um eine Ausgabe wie "0x00" zu erzwingen, können Sie printf "0x% 02X"
gbetous
1
... und bcist nicht überall verfügbar (zumindest nicht unter meinem eingebetteten Linux).
Matthieu
69

Hexidezimal bis Dezimal:

$ echo $((0xfee10000))
4276158464

Dezimal bis hexadezimal:

$ printf '%x\n' 26
1a
pjhobbs
quelle
15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff
Orwellophil
quelle
1
-v VARist eine Bash-Erweiterung. Nicht in der Manpage erwähnt , nur enthüllt, wenn man printfohne Argumente anruft
Adrian W
5

Entschuldigung, meine Schuld, versuchen Sie das ...

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

Beispiel:

$ ./dtoh 1024
400
pjhobbs
quelle
1
Danke, das hat env sehr geholfen. wo printfund hexBefehle sind nicht verfügbar.
Benchuk
2
@benchuk wo ist printfnicht verfügbar?
Matthieu
4

Versuchen:

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

In zshkönnen Sie so etwas tun:

% 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

Beispiel aus der zshDokumentseite zur arithmetischen Auswertung .

Ich glaube, Bash hat ähnliche Fähigkeiten.

Alastair
quelle
2

In meinem Fall bin ich auf ein Problem bei der Verwendung der printf-Lösung gestoßen:

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

Der einfachste Weg war die Verwendung einer Lösung mit bc , die in der höheren Veröffentlichung vorgeschlagen wurde:

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

Daniel Jeznach
quelle
Was fügt Ihre Lösung zu den vor Jahren geschriebenen hinzu?
Matthieu
@Matthieu Es wird das Problem von Zahlen mit führenden Nullen erwähnt, das Bash printf nicht hilfreich als oktal interpretiert, und eine Lösung demonstriert, die das Problem vermeidet.
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
quelle
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
quelle
1

Dies ist kein Shell-Skript, aber es ist das CLI-Tool, mit dem ich Zahlen zwischen bin / oct / dec / hex konvertiere:

    #!/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
quelle