
Eu tenho um arquivo instructions.txt
com o conteúdo:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Como posso criar um arquivo binário instructions.bin
com os mesmos dados do instructions.txt
. Em outras palavras, o .bin
arquivo deve ter os mesmos 192 bits que estão no .txt
arquivo, com 32 bits por linha. Estou usando o bash no Ubuntu Linux. Eu estava tentando usar, xxd -b instructions.txt
mas a saída é muito maior que 192 bits.
Responder1
oneliner para converter strings de uns e zeros de 32 bits em binário correspondente:
$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin
o que faz:
perl -ne
irá iterar através de cada linha do arquivo de entrada fornecido em STDIN (instructions.txt
)pack("B32", $_)
pegará uma lista de strings de 32 bits ($_
que acabamos de ler em STDIN) e a converterá em valor binário (você poderia alternativamente usar"b32"
se quisesse uma ordem crescente de bits dentro de cada byte em vez de uma ordem decrescente de bits; vejaperldoc -f pack
para mais detalhes)print
geraria então esse valor convertido para STDOUT, que então redirecionamos para nosso arquivo binárioinstructions.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 ....
Responder2
Adicionar a -r
opção (modo reverso) a xxd -b
não funciona como esperado, porque xxd simplesmente não suporta a combinação desses dois sinalizadores (ele ignora -b
se ambos forem fornecidos). Em vez disso, você deve primeiro converter os bits em hexadecimal. Por exemplo assim:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
Explicação completa:
- A parte entre parênteses cria um
bc
script. Primeiro ele define a base de entrada como binária (2) e a base de saída como hexadecimal (16). Depois disso, osed
comando imprime o conteúdoinstructions.txt
com ponto e vírgula entre cada grupo de 4 bits, o que corresponde a 1 dígito hexadecimal. O resultado é canalizado parabc
. - O ponto e vírgula é um separador de comando
bc
, portanto, tudo o que o script faz é imprimir todos os números inteiros de entrada (após a conversão da base). - A saída de
bc
é uma sequência de dígitos hexadecimais, que pode ser convertida em um arquivo com o formatoxxd -r -p
.
Saída:
$ 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 ....
Responder3
Meuresposta originalestava incorreto - xxd
não posso aceitar um -p
ou -r
com -b
...
Dado que as outras respostas são viáveis, e no interesse de "outra maneira", que tal o seguinte:
Entrada
$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Saída
$ 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
- desnecessário, mas usado para maior clarezatr -d $'\n'
- remova todas as novas linhas da entradaread -N 4 nibble
- lerexatamente4× caracteres nanibble
variávelprintf '%x' "$((2#${nibble}))"
converter o nibble de binário para 1× caractere hexadecimal$((2#...))
- converter o valor fornecido da base 2 (binária) para a base 10 (decimal)printf '%x'
- formatar o valor fornecido da base 10 (decimal) para a base 16 (hexadecimal)
xxd -r -p
- inverter (-r
) um despejo simples (-p
) - de hexadecimal para binário bruto
Pitão:
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
- Um não citadoheredoc(
<< EOF
) é usado para inserir conteúdo no código Python- Isto não é eficiente se a entrada se tornar grande
cat
etr
- usado para obter uma entrada limpa (uma linha)range(0, len(d), 8)
- obtenha uma lista de números de 0 ao final da stringd
, avançando 8× caracteres por vez.chr(int(d[i:i+8],2))
- converter a fatia atual (d[i:i+8]
) de binário para decimal (int(..., 2)
) e depois para um caractere bruto (chr(...)
)[ x for y in z]
-compreensão da lista''.join(...)
- converter a lista de caracteres em uma única stringprint(...)
- imprima
Responder4
arquivos binários não separam linhas com caracteres de nova linha. Arquivos binários não possuem delimitadores; é apenas um arquivo com vários 0 e 1, armazenado em algum dispositivo organizado em setores controlados pela tabela de alocação de arquivos ou mapeamento semelhante para dar significado.
Você pode converter o arquivo de texto como está, para binário, resultando em 192 bits (24 bytes) ou adicionar um caractere de nova linha após cada sequência de 32 bits para fornecer um arquivo com 6 bytes extras.
O código abaixo fornece um arquivo de 192 bits, conforme solicitado:
for x in $(cat file.txt);
do s=${x:0:32};
echo $(printf '%08X' "$((2#$s))");
done | xxd -r -p > file.bin
A alternativa é ler 8 bits por vez se não quiser código extra para preenchimento (linhas de 4 bytes no arquivo de texto)
Testado no Ubuntu 16.04.7