Agregando el -r
opción (modo inverso) a xxd -b
en realidad no funciona según lo previsto, porque xxd simplemente no admite la combinación de estas dos banderas (ignora -b
si se dan ambos). En su lugar, primero debe convertir los bits en hexadecimales. Por ejemplo, así:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
Explicación completa:
- La parte dentro de los paréntesis crea un
bc
guion. Primero establece la base de entrada en binario (2) y la base de salida en hexadecimal (16). Después de eso, elsed
el comando imprime el contenido deinstructions.txt
con un punto y coma entre cada grupo de 4 bits, lo que corresponde a 1 dígito hexadecimal. El resultado se canaliza abc
. - El punto y coma es un separador de comando en
bc
, por lo que todo lo que hace el script es imprimir cada entero de entrada (después de la conversión base). - La salida de
bc
es una secuencia de dígitos hexadecimales, que se puede convertir en un archivo con el habitualxxd -r -p
.
Salida:
$ 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 para convertir cadenas de 32 bits de unos y ceros en el binario correspondiente:
$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
qué hace:
perl -ne
iterará a través de cada línea del archivo de entrada proporcionado en STDIN (instructions.txt
)pack("B32", $_)
tomará una lista de cadenas de 32 bits ($_
que acabamos de leer de STDIN), y convertirlo a valor binario (alternativamente, podría usar"b32"
si desea un orden de bits ascendente dentro de cada byte en lugar de un orden de bits descendente; verperldoc -f pack
para más detalles)print
luego enviaría ese valor convertido a STDOUT, que luego redirigiríamos a nuestro archivo binarioinstructions.bin
verificar:
$ 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 ....
Mi respuesta original era incorrecta:xxd
no puede aceptar ninguno -p
o -r
con -b
...
Dado que las otras respuestas son viables y en aras de "otra manera ", ¿qué tal lo siguiente:
Entrada
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Salida
$ 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
Canalización de Bash:
cat instructions.txt \
| tr -d $'\n' \
| while read -N 4 nibble; do
printf '%x' "$((2#${nibble}))"; \
done \
| xxd -r -p \
> instructions.bin
cat
- innecesario, pero usado para mayor claridadtr -d $'\n'
- elimina todas las líneas nuevas de la entradaread -N 4 nibble
- leer exactamente 4× caracteres en elnibble
variablesprintf '%x' "$((2#${nibble}))"
convierte el nibble de binario a 1× carácter hexadecimal$((2#...))
- convertir el valor dado de base 2 (binario) a base 10 (decimal)printf '%x'
- formatee el valor dado de base 10 (decimal) a base 16 (hexadecimal)
xxd -r -p
- inversa (-r
) un volcado simple (-p
) - de hexadecimal a binario sin formato
Pitón:
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 sin comillas (
<< EOF
) se usa para obtener contenido en el código de Python- Esto no es eficiente si la entrada se vuelve grande
cat
ytr
- utilizado para obtener una entrada limpia (una línea)range(0, len(d), 8)
- obtener una lista de números desde 0 hasta el final de la cadenad
, avanzando 8× caracteres a la vez.chr(int(d[i:i+8],2))
- convertir el segmento actual (d[i:i+8]
) de binario a decimal (int(..., 2)
), y luego a un carácter sin formato (chr(...)
)[ x for y in z]
- comprensión de listas''.join(...)
- convertir la lista de caracteres en una sola cadenaprint(...)
- imprimirlo