Hexadezimal bis Dezimal im Shell-Skript

126

Kann mir jemand helfen, eine Hexadezimalzahl in einem Shell-Skript in eine Dezimalzahl umzuwandeln?

Ich möchte beispielsweise die Hexadezimalzahl bfca3000mithilfe eines Shell-Skripts in eine Dezimalzahl konvertieren . Ich möchte grundsätzlich die Differenz zweier Hexadezimalzahlen.

Mein Code lautet:

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

Bei der Ausführung erhalte ich folgende Fehlermeldung:

Line 48: -: syntax error: operand expected (error token is "-")
VenkateshJN
quelle
Umgekehrt : stackoverflow.com/questions/378829/… . Im Wesentlichen die gleichen Werkzeuge. Und mögliches Cross-Site-Duplikat von: superuser.com/questions/226163/…
Ciro Santilli 法轮功 冠状 病 六四 事件 12

Antworten:

313

Um von hexadezimal nach dezimal zu konvertieren, gibt es viele Möglichkeiten, dies in der Shell oder mit einem externen Programm zu tun:

Mit ::

$ echo $((16#FF))
255

mit ::

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

mit ::

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

mit ::

$ printf "%d\n" 0xFF
255

mit ::

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

mit ::

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

mit ::

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

mit ::

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

mit ::

$ groovy -e 'println Integer.parseInt("FF",16)'
255
Gilles Quenot
quelle
1
Was? bc ist eine beliebige Präzisionsrechnersprache : ein externer Befehl.
Gilles Quenot
10
Und so ? Dies ist genau der Zweck meiner 4 Befehle, bevor Sie den Sinn Ihrer Frage ändern.
Gilles Quenot
2
Ist die printfLösung POSIX? Wenn ja, ist es das Beste :)
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
3
In Bash können Sie auch verwenden $((0xff)), dh mit C-ähnlichem Hex-Präfix anstelle von 16#, obwohl dies N#deutlich allgemeiner ist.
Ruslan
3
Das erste Bash-Beispiel ist anfällig für Ganzzahlüberlauffehler, z. B. echo $((077E9F2DBF49D100001#FF))Überlauf der 64-Bit-Ganzzahlgrenze von 2 ^ 64. bcbehandelt dies richtig.
Roblogic
39

Der Umgang mit einer sehr leichten eingebetteten Version von Busybox unter Linux bedeutet, dass viele der herkömmlichen Befehle nicht verfügbar sind (bc, printf, dc, perl, python).

echo $((0x2f))
47

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

Dank an Peter Leung für diese Lösung.

hinekyle
quelle
1
OK, aber Vorsicht vor Integer-Überlauffehlern, z. B. echo $((0x077E9F2DBF49D100001))Überlaufen der 64-Biit-Integer-Grenze von 2 ^ 64. bcbehandelt dies richtig
Roblogic
13

Eine weitere Möglichkeit, dies mit der Shell zu tun (bash oder ksh, funktioniert nicht mit Bindestrich):

echo $((16#FF))
255
Tomás Fox
quelle
Was bedeutet das #Symbol? Gibt es andere Anwendungen oder Dokumentationen, um mehr über die Verwendung zu erfahren?
user1527227
1
Es wird hier erwähnt: Link . Am Ende von Abschnitt 6.5 heißt es: "... Zahlen haben die Form [Basis #] n, wobei die optionale Basis eine Dezimalzahl zwischen 2 und 64 ist, die die arithmetische Basis darstellt, und n eine Zahl in dieser Basis ist. Wenn Die Basis # wird weggelassen, dann wird die Basis 10 verwendet. Die Ziffern größer als 9 werden durch die Kleinbuchstaben, die Großbuchstaben '@' und '_' in dieser Reihenfolge dargestellt. Wenn die Basis kleiner oder gleich 36 ist, Klein- und Großbuchstaben können austauschbar verwendet werden, um Zahlen zwischen 10 und 35 darzustellen. "
Tomás Fox
11

Innerhalb einer Shell stehen Ihnen verschiedene Tools zur Verfügung. Sputnick hat Ihnen anhand Ihrer ersten Frage einen hervorragenden Überblick über Ihre Optionen gegeben. Er verdient definitiv Stimmen für die Zeit, die er damit verbracht hat, Ihnen mehrere richtige Antworten zu geben.

Eine weitere, die nicht auf seiner Liste steht:

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

Aber wenn Sie nur subtrahieren möchten, warum sollten Sie dann die Eingabe auf Basis 10 ändern?

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

Der dcBefehl lautet "Desk Calc". Es werden auch Eingaben von stdin wie verwendet bc, aber anstatt "Reihenfolge der Operationen" zu verwenden, wird die Stapelnotation ("umgekehrte polnische") verwendet. Sie geben ihm Eingaben, die er einem Stapel hinzufügt, geben ihm dann Operatoren, die Elemente vom Stapel entfernen, und drücken die Ergebnisse zurück.

In den obigen Befehlen haben wir Folgendes:

  • 16i- Weist DC an, Eingaben in Basis 16 (hexadezimal) zu akzeptieren. Ändert die Ausgangsbasis nicht.
  • BFCA3000 - Ihre ursprüngliche Nummer
  • 17FF - eine zufällige Hex-Zahl, die ich ausgewählt habe, um von Ihrer ursprünglichen Zahl abzuziehen
  • - - Nehmen Sie die beiden Zahlen, die wir gedrückt haben, und subtrahieren Sie die spätere von der früheren. Schieben Sie dann das Ergebnis zurück auf den Stapel
  • p- Drucken Sie das letzte Element auf dem Stapel. Dies ändert den Stapel nicht, also ...
  • 10o - weist dc an, seine Ausgabe in der Basis "10" zu drucken, aber denken Sie daran, dass unser Eingabenummerierungsschema derzeit hexadezimal ist, sodass "10" "16" bedeutet.
  • p - Drucke den letzten Gegenstand erneut auf den Stapel ... diesmal in hex.

Mit DC können Sie sagenhaft komplexe mathematische Lösungen erstellen. Es ist eine gute Sache, Shell-Skripte in Ihrer Toolbox zu haben.

Ghoti
quelle
3

Der gemeldete Fehler wird angezeigt, wenn die Variablen null (oder leer) sind:

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

Dies könnte passieren, weil der Wert für bc falsch war. Das könnte gut sein, dass bc UPPERcase-Werte benötigt. Es braucht BFCA3000nicht bfca3000. Das lässt sich leicht in Bash beheben, verwenden Sie einfach die ^^Erweiterung:

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

Dadurch wird das Skript folgendermaßen geändert:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

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

echo "Diference $var5"

Es ist jedoch nicht erforderlich, bc [1] zu verwenden, da bash die Übersetzung und Subtraktion direkt durchführen könnte:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

echo "Diference $var5"

[1] Hinweis: Ich gehe davon aus, dass die Werte in 64-Bit-Mathematik dargestellt werden können, da die Differenz in Ihrem ursprünglichen Skript in Bash berechnet wurde. Bash ist auf Ganzzahlen kleiner als ((2 ** 63) -1) beschränkt, wenn es in 64 Bit kompiliert wird. Dies ist der einzige Unterschied zu bc, für den es keine solche Grenze gibt.


quelle
3

In Dash und anderen Shells können Sie verwenden

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

um eine Hexadezimalzahl in eine Dezimalzahl umzuwandeln. Dies ist nicht bash oder ksh-spezifisch.

Anfänger
quelle
1
zBprintf "%d" 0xff
Lashgar