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
bcguion. Primero establece la base de entrada en binario (2) y la base de salida en hexadecimal (16). Después de eso, elsedel comando imprime el contenido deinstructions.txtcon 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
bces 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 -neiterará 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 packpara más detalles)printluego 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 elnibblevariablesprintf '%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
catytr- 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