J'ai un fichier instructions.txt
avec le contenu:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Comment créer un fichier binaire instructions.bin
avec les mêmes données que instructions.txt
En d'autres termes, le fichier .bin
doit avoir les mêmes 192 bits que le fichier .txt
, avec 32 bits par ligne. J'utilise bash sur Ubuntu Linux. J'essayais d'utiliser xxd -b instructions.txt
mais la sortie est bien plus longue que 192 bits.
oneliner pour convertir les chaînes de 32 bits de uns et de zéros en fichiers binaires correspondants:
$ Perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
ce qu'il fait:
Perl -ne
va parcourir chaque ligne du fichier d'entrée fourni sur STDIN (instructions.txt
)pack("B32", $_)
prendra une liste de chaînes de 32 bits ($_
que nous venons de lire dans STDIN) et la convertira en valeur binaire (vous pouvez également utiliser "b32"
si vous voulez un ordre croissant des bits dans chaque octet au lieu d'un ordre décroissant; voir perldoc -f pack
pour plus d'informations. détails)print
afficherait alors cette valeur convertie en STDOUT, que nous redirigerons ensuite vers notre fichier binaire instructions.bin
vérifier:
$ 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 ....
L'ajout de l'option -r
(mode inverse) à xxd -b
ne fonctionne pas comme prévu, car xxd ne prend tout simplement pas en charge la combinaison de ces deux indicateurs (il ignore -b
si les deux sont indiqués). Au lieu de cela, vous devez d'abord convertir les bits pour vous en servir. Par exemple comme ceci:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
Explication complète:
bc
. Il définit d'abord la base d'entrée sur binaire (2) et la base de sortie sur hexadécimale (16). Après cela, la commande sed
imprime le contenu de instructions.txt
avec un point-virgule entre chaque groupe de 4 bits, ce qui correspond à 1 chiffre hexadécimal. Le résultat est transféré dans bc
.bc
. Le script n'imprime donc que tous les entiers en entrée (après la conversion de base).bc
est une séquence de chiffres hexadécimaux, qui peuvent être convertis en un fichier avec le xxd -r -p
habituel.Sortie:
$ 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 ....
Ma réponse originale était incorrecte - xxd
ne peut accepter ni -p
ni -r
avec -b
...
Etant donné que les autres réponses sont réalisables, et dans l’intérêt de ", une autre manière ", que diriez-vous de ce qui suit:
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
$ 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
Pipeline Bash:
cat instructions.txt \
| tr -d $'\n' \
| while read -N 4 nibble; do
printf '%x' "$((2#${nibble}))"; \
done \
| xxd -r -p \
> instructions.bin
cat
- inutile, mais utilisé pour plus de clartétr -d $'\n'
- supprime toutes les nouvelles lignes de l'entréeread -N 4 nibble
- lire exactement 4 × caractères dans la variable nibble
printf '%x' "$((2#${nibble}))"
convertit le quartet de binaire en 1 × caractère hexadécimal $((2#...))
- convertit la valeur donnée en base 2 (binaire) en base 10 (décimale)printf '%x'
- formate la valeur donnée de la base 10 (décimale) à la base 16 (hexadécimale)xxd -r -p
- inverse (-r
) un vidage simple (-p
) - de l'hexadécimal au binaire brutPython:
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
<< EOF
) est utilisé pour obtenir du contenu dans le code Python cat
et tr
- utilisé pour obtenir une entrée propre (une ligne)range(0, len(d), 8)
- Obtenir une liste de nombres de 0 à la fin de la chaîne d
, en passant à 8 × caractères à la fois.chr(int(d[i:i+8],2))
- convertit la tranche actuelle (d[i:i+8]
) de binaire en décimal (int(..., 2)
), puis en un caractère brut (chr(...)
)[ x for y in z]
- liste compréhension''.join(...)
- convertit la liste de caractères en une seule chaîneprint(...)
- l'imprimerVous pouvez aussi bien essayer de poster ceci sur le site CodeGolf SE, mais voici ma version alternative de Python (juste pour le défi):
python -c "import sys,struct;[sys.stdout.buffer.write(struct.pack('!i',int(x,2)))for x in sys.stdin]" \
< input.txt > output.bin
En supposant que input.txt
contient vos données, elles sont formatées à 32 caractères par ligne.
Ceci utilise le paquet struct
de Python 3 et l’écriture/la lecture sur stdin/out. (En Python 2, cela aurait été plus court).