Binärdaten in der Bash-Shell verarbeiten

Binärdaten in der Bash-Shell verarbeiten

Neben den bekannten Möglichkeiten zur Verabeitung von Textdaten bieten Bash &Co. Funktionen für den Umgang mit Binärdaten. Wir zeigen, wie man sie nutzt.

Die Bash-Shell ist eine der vielfältigsten Skripting-Umgebungen unter Linux. Im Rückgriff auf die verfügbaren Linux- und Unix-Tools werden Shell-Skripts typischerweise zur Verarbeitung von Textdateien und dem Management der Unix-Umgebung wie etwa Prozessen verwendet.

Eine Anwendung, für die die Bash nicht unbedingt bekannt ist, ist Verarbeitung von Daten auf Bitebene. Die Bash bietet aber auch dafür zahlreiche Möglichkeiten, die wir in diesem Artikel näher vorstellen.

Anzeigen und verarbeiten

Zwei Tools, die Sie verwenden können, um Daten hexadezimal und binär anzuzeigen, sind hexdump und xxd. Während xxd weniger Optionen bietet als hexdump, kann es eine Sache, die hexdump fehlt: hexadezimale Strings in Binärdaten umwandeln. Der folgene Aufruf gibt die einzelnen Zeichen des Strings "hello" als Hexadezimalwerte aus:

echo -n "hello" | xxd -p
68656c6c6f

In dem folgenden Befehl wandelt xxd Hexadezimalwerte in etwas um, das die Manpage des Tools eine "mail-safe ASCII representation" nennt:

echo -n "6162" | xxd -p -r
ab

Da die hexadezimalen Werte 61 und 62 den ASCII-Zeichen "a" und "b" entsprechen ist der ausgegebene Wert "ab". Diese beiden Aufrufe lassen sich in Bash-Funktionen verpacken, um sie in eigenen Skripts umstandslos zu verwenden, etwa so:

pack() {
   echo -n "$1" | xxd -p -r
}
unpack() {
   echo -n "$1" | xxd -p
}

Bisher haben alle Aufrufe von den Switch "-p" verwendet, der dem Tool mitteilt, dass die Eingabe hexcodiert ist, also jedes 8-Bit-Byte einer zweistelligen Hexdarstellung entspricht. Um Binärdaten als Binärstring auszugeben (also mit Nullen und Einsen), verwenden Sie den Schalter "-b":

tobin() {
    echo -n "$1" | xxd -b -g0 | awk '{ printf("%s", $2)}'
}
tobin ab
0110000101100010

Hier wird die Zeichenkette "ab" in einen Binärstring umgewandelt, der die beiden 8-Bit-Werte 01100001 und 01100010 enthält.

Binärdaten umwandeln

Die Bash bietet einige Befehlem, um Binärdaten mit mathematischen und logischen Ausdrücken umzuwandeln. Dieser Vorgang wird "arithmetic expansion" genannt. Eine einfache Berechnung sieht dabei so aus:

echo $(( 4*5 ))
20

Weitergehende Berechnungen können Sie beispielsweise mit dem externen Tool bc durchführen, das Befehle von der Standardeingabe stdin lesen kann:

echo "4*5" | bc
20

Die Berechnung wird mit der Basis 10 (dezimal) ausgeführt. Um mit bc ein anderes Zahlensystem zu verwenden, müssen Sie die entsprechende Basis angeben. Wenn Sie beispielsweise mit Hexzahlen rechnen wollen, können Sie eine Funktion wie die folgende verwenden:

hexadd() {
    echo "obase=16;ibase=A;$((16#$1))+$2" | bc
}
hexadd A 2
C

Hier gibt "obase" die Basis für die Ausgabe an, während "ibase" die Basis für die Eingabe festlegt. Schließlich wird noch von der arithmetischen Expansion der Bash Gebrauch gemacht, die hier den Operator "#" verwendet, um den dahinter folgenden Wert mit der davor stehenden Basis ins Dezimalsystem umzuwandeln. Hier wird der hexadezimale Wert A ins Dezimalsystem konvertiert (Ergebnis: 10) und dann mit bc zu 2 addiert, was zusammen 12 ergibt. Das Ergebnis konvertiert wieder nach Hex, was die Ausgabe "C" ergibt.

Auch bitweise Operationen wie AND, OR, XOR und Shift sind möglich. AND (&) gibt alle Bits aus, die bei beiden Operanden auf 1 gesetzt sind. Das Ergebnis eines OR (|) ist ein Wert, der alle Bits auf 1 gesetzt hat, die bei einem der beiden Operanden einen 1 enthält. XOR (^) setzt alle Bits auf 1, die sich bei den beiden Eingabewerten unterscheiden.

In Listing 1 ermittelt der erste Aufruf ein binäres AND der Dezimalwerte 3 (0011) und 6 (0110). Da sie nur das zweite Bit gemeinsam gesetzt haben, ist die Ausgabe 0010, also 2. Ein binäres OR ergibt bei diesen beiden Operanden 7 (0111), während ein XOR zur Ausgabe 5 (0101) ergibt.

Listing 1: Bitweise Operatoren

logicand() {
  echo $(($1&$2))
}
logicor() {
  echo $(($1|$2))
}
logicxor() {
  echo $(($1^$2))
}
$ logicand 3 6
2
$ logicor 3 6
7
$ logicxor 3 6
5

Ein weitere bitweise Operation ist das Shift, das nach links oder rechts erfolgen kann. Listing 2 zeigt den Code für ein left Shift und ein right Shift, die mit den entsprechenden Operatoren in der Bash realisiert sind ("<<" und ">>").

Listing 2: Shift

shiftr() {
  echo $(($1>>$2))
}
shiftl() {
  echo $(($1<<$2))
}
$ shiftl 4 2
16
$ shiftr 16 4
1

Ähnliche Artikel

comments powered by Disqus

Artikel der Woche

Loadtests ohne Server

Für Loadtests der eigenen Server bietet sich die Cloud an, denn kurz getaktet lassen sich dort viele Rechnerinstanzen starten, die das eigene Budget nur wenig belasten. Noch flexibler, günstiger und besser skalierbar sind Tests mit einer Serverless-Infrastruktur wie AWS Lambda. Wir führen vor, wie Sie dort mit Serverless Artillery eigene Loadtests starten. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Container

Wie setzen Sie Container ein?

  • Gar nicht
  • Docker standalone
  • Docker mit Kubernetes
  • Docker mit Swarm
  • Docker mit anderem Management
  • LXC/LXD
  • Rocket
  • CRI-O auf Kubernetes
  • Container auf vSphere
  • Andere (siehe Kommentare auf der Ergebnisseite)

Google+

Ausgabe /2018

Microsite