
Ich habe eine Datei instructions.txt
mit dem Inhalt:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Wie kann ich eine Binärdatei instructions.bin
mit denselben Daten wie erstellen instructions.txt
? Mit anderen Worten, die .bin
Datei sollte dieselben 192 Bits haben wie die .txt
Datei selbst, mit 32 Bits pro Zeile. Ich verwende Bash unter Ubuntu Linux. Ich habe versucht, es zu verwenden, xxd -b instructions.txt
aber die Ausgabe ist viel länger als 192 Bits.
Antwort1
Oneliner zum Konvertieren von 32-Bit-Zeichenfolgen aus Einsen und Nullen in entsprechende Binärzahlen:
$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
Was es macht:
perl -ne
durchläuft jede Zeile der Eingabedatei, die über STDIN (instructions.txt
) bereitgestellt wirdpack("B32", $_)
nimmt eine Zeichenfolgenliste mit 32 Bits ($_
die wir gerade von STDIN gelesen haben) und konvertiert sie in einen Binärwert (Sie können dies alternativ verwenden,"b32"
wenn Sie innerhalb jedes Bytes eine aufsteigende statt einer absteigenden Bitreihenfolge wünschen; sieheperldoc -f pack
für weitere Details)print
würde dann den konvertierten Wert an STDOUT ausgeben, den wir dann an unsere Binärdatei weiterleiteninstructions.bin
verifizieren:
$ hexdump -Cv instructions.bin
00000000 00 00 00 13 02 d1 20 83 00 73 02 b3 00 73 04 33 |...... ..s...s.3|
00000010 00 73 64 b3 00 00 00 13 |.sd.....|
00000018
$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011 ....
00000004: 00000010 11010001 00100000 10000011 .. .
00000008: 00000000 01110011 00000010 10110011 .s..
0000000c: 00000000 01110011 00000100 00110011 .s.3
00000010: 00000000 01110011 01100100 10110011 .sd.
00000014: 00000000 00000000 00000000 00010011 ....
Antwort2
Das Hinzufügen der -r
Option (Reverse Mode) xxd -b
funktioniert nicht wie vorgesehen, da xxd die Kombination dieser beiden Flags einfach nicht unterstützt (es ignoriert, -b
wenn beide angegeben sind). Stattdessen müssen Sie die Bits zuerst selbst in Hex umwandeln. Zum Beispiel so:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
Vollständige Erklärung:
- Der Teil in den Klammern erstellt ein
bc
Skript. Es setzt zuerst die Eingabebasis auf binär (2) und die Ausgabebasis auf hexadezimal (16). Danachsed
druckt der Befehl den Inhalt voninstructions.txt
mit einem Semikolon zwischen jeder Gruppe von 4 Bits aus, was 1 Hexadezimalziffer entspricht. Das Ergebnis wird in weitergeleitetbc
. - Das Semikolon ist ein Befehlstrennzeichen in
bc
, daher druckt das Skript lediglich alle eingegebenen Ganzzahlen wieder aus (nach der Basiskonvertierung). - Die Ausgabe
bc
ist eine Folge von Hex-Ziffern, die mit dem üblichen in eine Datei konvertiert werden kannxxd -r -p
.
Ausgabe:
$ hexdump -Cv instructions.bin
00000000 00 00 00 13 02 d1 20 83 00 73 02 b3 00 73 04 33 |...... ..s...s.3|
00000010 00 73 64 b3 00 00 00 13 |.sd.....|
00000018
$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011 ....
00000004: 00000010 11010001 00100000 10000011 .. .
00000008: 00000000 01110011 00000010 10110011 .s..
0000000c: 00000000 01110011 00000100 00110011 .s.3
00000010: 00000000 01110011 01100100 10110011 .sd.
00000014: 00000000 00000000 00000000 00010011 ....
Antwort3
Meinursprüngliche Antwortwar falsch – kann weder „ oder“ mit … xxd
akzeptieren .-p
-r
-b
Da die anderen Antworten praktikabel sind und im Interesse von „ein anderer Weg", wie wäre es mit folgendem:
Eingang
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Ausgabe
$ hexdump -Cv < instructions.bin
00000000 00 00 00 13 02 d1 20 83 00 73 02 b3 00 73 04 33 |...... ..s...s.3|
00000010 00 73 64 b3 00 00 00 13 |.sd.....|
00000018
Bash-Pipeline:
cat instructions.txt \
| tr -d $'\n' \
| while read -N 4 nibble; do
printf '%x' "$((2#${nibble}))"; \
done \
| xxd -r -p \
> instructions.bin
cat
- unnötig, wird aber der Übersichtlichkeit halber verwendettr -d $'\n'
- alle Zeilenumbrüche aus der Eingabe entfernenread -N 4 nibble
- lesengenau4× Zeichen in dienibble
Variableprintf '%x' "$((2#${nibble}))"
Konvertieren Sie das Nibble von binär in 1× Hex-Zeichen$((2#...))
- Konvertieren Sie den angegebenen Wert von der Basis 2 (binär) in die Basis 10 (dezimal)printf '%x'
- formatiert den angegebenen Wert von Basis 10 (dezimal) nach Basis 16 (hexadezimal)
xxd -r -p
- reverse (-r
) einen einfachen Dump (-p
) - von hexadezimal nach rohem Binär
Python:
python << EOF > instructions.bin
d = '$(cat instructions.txt | tr -d $'\n')'
print(''.join([chr(int(d[i:i+8],2)) for i in range(0, len(d), 8)]))
EOF
- Ein nicht zitierterhierdoc(
<< EOF
) wird verwendet, um Inhalte in den Python-Code zu bekommen- Dies ist nicht effizient, wenn der Input groß wird
cat
undtr
- wird verwendet, um eine saubere (einzeilige) Eingabe zu erhaltenrange(0, len(d), 8)
- Holen Sie sich eine Liste mit Zahlen von 0 bis zum Ende der Zeichenfolged
, wobei Sie jeweils 8 Zeichen lang sind.chr(int(d[i:i+8],2))
- Konvertieren Sie den aktuellen Slice (d[i:i+8]
) von Binär in Dezimal (int(..., 2)
) und dann in ein Rohzeichen (chr(...)
)[ x for y in z]
-Listenverständnis''.join(...)
- Konvertieren Sie die Liste der Zeichen in eine einzelne Zeichenfolgeprint(...)
- Druck es
Antwort4
Binärdateien trennen Zeilen nicht durch Zeilenumbruchzeichen. Binärdateien haben keine Trennzeichen; es ist nur die eine Datei mit einer Reihe von 0 und 1, die auf einem Gerät gespeichert ist und in Sektoren angeordnet ist, die durch eine Dateizuordnungstabelle oder eine ähnliche Zuordnung gesteuert werden, um ihr Bedeutung zu verleihen.
Sie können die Textdatei entweder unverändert in eine Binärdatei mit einem Ergebnis von 192 Bit (24 Byte) konvertieren oder nach jeder 32-Bit-Sequenz ein Zeilenumbruchzeichen hinzufügen, um eine Datei mit 6 zusätzlichen Byte zu erhalten.
Der folgende Code gibt Ihnen wie gewünscht eine 192-Bit-Datei:
for x in $(cat file.txt);
do s=${x:0:32};
echo $(printf '%08X' "$((2#$s))");
done | xxd -r -p > file.bin
Alternativ können Sie jeweils 8 Bits lesen, wenn Sie keinen zusätzlichen Code zum Auffüllen wünschen (4-Byte-Zeilen in der Textdatei).
Getestet auf Ubuntu 16.04.7