
Tengo un archivo instructions.txt
con el contenido:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
¿Cómo puedo crear un archivo binario instructions.bin
con los mismos datos que instructions.txt
. En otras palabras, el .bin
archivo debe tener los mismos 192 bits que tiene .txt
, con 32 bits por línea. Estoy usando bash en Ubuntu Linux. Estaba intentando usarlo xxd -b instructions.txt
pero la salida es mucho más larga que 192 bits.
Respuesta1
oneliner para convertir cadenas de unos y ceros de 32 bits en el binario correspondiente:
$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
Que 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 la convertirá a un valor binario (también puede usarla"b32"
si desea un orden de bits ascendente dentro de cada byte en lugar de un orden de bits descendente; consulteperldoc -f pack
para obtener más detalles)print
luego enviaría ese valor convertido a STDOUT, que luego redirigiría 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 ....
Respuesta2
Agregar la -r
opción (modo inverso) en xxd -b
realidad no funciona según lo previsto, porque xxd simplemente no admite la combinación de estos dos indicadores (ignora -b
si se proporcionan ambos). En cambio, primero debes convertir los bits a hexadecimal. 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 del paréntesis crea un
bc
guión. Primero establece la base de entrada en binario (2) y la base de salida en hexadecimal (16). Después de eso, elsed
comando imprime el contenidoinstructions.txt
con un punto y coma entre cada grupo de 4 bits, que corresponde a 1 dígito hexadecimal. El resultado se canaliza abc
. - El punto y coma es un separador de comandos en
bc
, por lo que todo lo que hace el script es imprimir cada número entero de entrada (después de la conversión de base). - La salida de
bc
es una secuencia de dígitos hexadecimales, que se puede convertir en un archivo con el formato habitualxxd -r -p
.
Producción:
$ 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 ....
Respuesta3
Mirespuesta originalera incorrecto: xxd
no puedo aceptar ninguno de los dos -p
ni -r
con -b
...
Dado que las otras respuestas son viables y en interés de "de otra manera", ¿qué tal lo siguiente?
Aporte
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Producción
$ 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
Tubería 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'
- eliminar todas las nuevas líneas de la entradaread -N 4 nibble
- leerexactamente4× caracteres en lanibble
variableprintf '%x' "$((2#${nibble}))"
convertir 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
- invertir (-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 no citadoheredoc(
<< EOF
) se utiliza para introducir contenido en el código Python.- Esto no es eficiente si la entrada se vuelve grande.
cat
ytr
- usado para obtener una entrada limpia (de 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 la lista''.join(...)
- convertir la lista de caracteres en una sola cadenaprint(...)
- Imprímelo
Respuesta4
Los archivos binarios no separan líneas con caracteres de nueva línea. Los archivos binarios no tienen delimitadores; es solo un archivo con un montón de 0 y 1, almacenado en algún dispositivo organizado en sectores controlados por una tabla de asignación de archivos o un mapeo similar para darle significado.
Puede convertir el archivo de texto tal como está a binario, lo que da como resultado 192 bits (24 bytes) o agregar un carácter de nueva línea después de cada secuencia de 32 bits para obtener un archivo con 6 bytes adicionales.
El siguiente código le proporciona un archivo de 192 bits, según lo solicitado:
for x in $(cat file.txt);
do s=${x:0:32};
echo $(printf '%08X' "$((2#$s))");
done | xxd -r -p > file.bin
La alternativa es leer 8 bits a la vez si no desea código adicional para el relleno (líneas de 4 bytes en un archivo de texto)
Probado en Ubuntu 16.04.7