Wie kann ich 8 Bytes als vorzeichenloses int (Little Endian) 'lesen / interpretieren' ?
Vielleicht gibt es dafür eine magische Bash-Fu-Konvertierung?
UPDATE:
Es scheint, dass bei der Interpretation meiner Frage etwas überkreuzt wurde. Hier ist ein breiteres Beispiel dafür, was ich versuche zu tun.
Ich möchte die ersten (und letzten) 64 KB einer Datei lesen. Jedes 8-Byte-Wort ist als vorzeichenlose 64-Bit-Little-Endian-Ganzzahl zu interpretieren. Diese Ganzzahlen sollen in einer Hashing-Berechnung verwendet werden, die die Datei eindeutig identifiziert. Es müssen also viele Berechnungen durchgeführt werden. ∴ Geschwindigkeit wird bevorzugt, ist aber nicht kritisch. (Warum mache ich das? Weil smplayer
die Namen der INI-Dateien für abgespielte Medien gehasht werden und ich auf diese Dateien zugreifen und sie ändern möchte, ahme ich den C ++ - Code des Smplayers in Bash nach.)
Eine Lösung, die das Akzeptieren einer Piped-Eingabe ermöglicht, wäre optimal und wahrscheinlich aufgrund der Art und Weise, wie Bash-Variablen \ x00 nicht verarbeiten können, von wesentlicher Bedeutung.
Mir ist klar, dass so etwas wahrscheinlich besser für Python, Perl und C / C ++ geeignet ist, aber ich kenne Python und Perl nicht, und obwohl ich es in C ++ tun könnte, ist es Jahre her, seit ich es verwendet habe Ich versuche mich auf Bash zu konzentrieren.
Kurze Perl- und Python-Schnipsel sind gut. Bash wird bevorzugt (aber nicht unter Geschwindigkeitseinbußen).
quelle
ö§«¢
sind keine Bytes; Es handelt sich nominell um Unicode-Zeichen, die bei der Codierung in UTF-8 und UTF-32 8 Byte und bei der Codierung in UTF-32 16 Byte verwenden. Wie in Manpages häufig anzutreffen, beziehe ich mich auf 8-Bit-Oktette. Nur ein gewöhnliches 8-Bit-Byte. Ich möchte 8 davon als 64-Bit-Big-Endian-IntAntworten:
Bash ist das falsche Werkzeug. Muscheln können gut Teile zusammenkleben; Textverarbeitung und Arithmetik werden nebenbei bereitgestellt, und die Datenverarbeitung liegt überhaupt nicht in ihrem Zuständigkeitsbereich.
Ich würde Python über Perl wählen, weil Python auf Anhieb Bignums hat. Verwenden Sie
struct.unpack
diese Option, um die Daten zu entpacken.Hier ist meine Antwort auf die ursprüngliche Frage. Die überarbeitete Frage hat nicht viel mit dem Original zu tun, bei dem es darum ging, eine 8-Byte-Sequenz in die 64-Bit-Ganzzahl umzuwandeln, die sie in Little-Endian-Reihenfolge darstellt.
Ich glaube nicht, dass bash eine eingebaute Funktion dafür hat. Das folgende Snippet wird
a
auf eine Zeichenfolge gesetzt, die die hexadezimale Darstellung der Zahl ist, die den Bytes in der angegebenen Zeichenfolge in Big-Endian- Reihenfolge entspricht.Kehren Sie für die Little-Endian-Reihenfolge die Reihenfolge der Bytes in der ursprünglichen Zeichenfolge um. In Bash und für eine Zeichenfolge bekannter Länge können Sie dies tun
Sie können auch die bevorzugte Endianität Ihrer Plattform ermitteln, wenn Sie
od
8-Byte-Typen unterstützen.Ob Sie rechnen
$a
können, hängt davon ab, ob Ihre Bash 8-Byte-Arithmetik unterstützt. Selbst wenn dies der Fall ist, wird es als signierter Wert behandelt.Alternativ können Sie Perl verwenden:
Wenn Ihr Perl ohne 64-Bit-Integer-Unterstützung kompiliert wird, müssen Sie die Bytes aufteilen.
(Ersetzen Sie es
<
durch>
Big-Endian oder entfernen Sie es, um die Plattform-Endianness zu erhalten.)quelle
Invalid type 'Q' in unpack at -e line 1.
... Der Befehl (mit einer Zeichenfolge von 8 zufälligen Bytes):perl -e 'print unpack "Q<", $ARGV[0]' "12345678"
... Die Ausgabe: nur die Fehlermeldung ... perl vereion: v5.10.1Gilles 'Python-Methode ist definitiv schneller, aber ich dachte, ich würde diese * Bash *** + *** Standard-Single-Purpose-Tools * einfach als allgemeines Mahlgut in die Mühle werfen. Es geht wahrscheinlich genauso um' bc ' wie alles andere ... Es gibt eine Menge Initialisierungsmaterial, um Eingabedateien mit weniger als 64 KB zu berücksichtigen ... Der Hash wird auf die Länge der Datei initialisiert, und dann wird jede der 64-Bit-Ganzzahlen nacheinander hinzugefügt es; verursacht (erwarteten) Integer-Überlauf .. hat es
bc
geschafft, den Trick zu machen ...quelle
Dies akzeptiert stdin und druckt die letzten 64 KB der Datei als vorzeichenlose 8-Byte-Hexadezimalzahlen in der Endianess des Computers (Little-Endian auf x86). Um die ersten 64 KB zu drucken, ersetzen Sie "Schwanz" durch "Kopf".
EINSCHRÄNKUNGEN: Der Versuch, die Ausgabe mit printf in eine Dezimalzahl umzuwandeln, führt zu Fehlern außerhalb des Bereichs
quelle