Aggiunta di -r
opzione (modalità inversa) a xxd -b
in realtà non funziona come previsto, perché xxd semplicemente non supporta la combinazione di questi due flag (ignora -b
se entrambi sono dati). Invece, devi prima convertire i bit in esadecimale da solo. Ad esempio in questo modo:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
Spiegazione completa:
- La parte all'interno delle parentesi crea un
bc
copione. Per prima cosa imposta la base di input su binario (2) e la base di output su esadecimale (16). Successivamente, ilsed
comando stampa il contenuto diinstructions.txt
con un punto e virgola tra ogni gruppo di 4 bit, che corrisponde a 1 cifra esadecimale. Il risultato viene reindirizzato inbc
. - Il punto e virgola è un separatore di comandi in
bc
, quindi tutto ciò che fa lo script è stampare tutti i numeri interi di input (dopo la conversione di base). - L'output di
bc
è una sequenza di cifre esadecimali, che può essere convertita in un file con il solitoxxd -r -p
.
Uscita:
$ 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 ....
oneliner per convertire stringhe a 32 bit di uno e zero nel binario corrispondente:
$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
cosa fa:
perl -ne
ripeterà ogni riga del file di input fornito su STDIN (instructions.txt
)pack("B32", $_)
prenderà un elenco di stringhe di 32 bit ($_
che abbiamo appena letto da STDIN) e convertirlo in valore binario (puoi in alternativa usare"b32"
se si desidera un ordine di bit crescente all'interno di ogni byte anziché un ordine di bit decrescente; vediperldoc -f pack
per maggiori dettagli)print
genererebbe quindi quel valore convertito in STDOUT, che poi reindirizzeremo al nostro file binarioinstructions.bin
verifica:
$ 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 ....
La mia risposta originale non era corretta - xxd
non può accettare né -p
o -r
con -b
...
Dato che le altre risposte sono realizzabili e nell'interesse di "un altro modo ", che ne dici di quanto segue:
Inserimento
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Uscita
$ 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
- non necessario, ma usato per chiarezzatr -d $'\n'
- rimuovere tutte le nuove righe dall'inputread -N 4 nibble
- leggi esattamente 4× caratteri nelnibble
variabileprintf '%x' "$((2#${nibble}))"
convertire il bocconcino da binario a 1× carattere esadecimale$((2#...))
- convertire il valore dato da base 2 (binario) a base 10 (decimale)printf '%x'
- formatta il valore dato da base 10 (decimale) a base 16 (esadecimale)
xxd -r -p
- inverso (-r
) un semplice dump (-p
) - da esadecimale a binario grezzo
Pitone:
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
- Un heredoc non quotato (
<< EOF
) viene utilizzato per inserire contenuto nel codice Python- Questo non è efficiente se l'input diventa grande
cat
etr
- utilizzato per ottenere un input pulito (una riga)range(0, len(d), 8)
- ottenere un elenco di numeri da 0 alla fine della stringad
, spostando 8× caratteri alla volta.chr(int(d[i:i+8],2))
- converte la slice corrente (d[i:i+8]
) da binario a decimale (int(..., 2)
), quindi a un carattere non elaborato (chr(...)
)[ x for y in z]
- comprensione dell'elenco''.join(...)
- convertire l'elenco di caratteri in una singola stringaprint(...)
- stampalo