mengonversi file teks bit ke file biner

12

Saya punya file instructions.txtdengan konten:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Bagaimana saya bisa membuat file biner instructions.bindari data yang sama dengan instructions.txt. Dengan kata lain .binfile harus sama 192 bit yang ada di .txtfile, dengan 32 bit per baris. Saya menggunakan bash di Ubuntu Linux. Saya mencoba menggunakan xxd -b instructions.txttetapi hasilnya jauh lebih lama dari 192 bit.

dopamane
sumber

Jawaban:

6

oneliner untuk mengonversi string 32-bit dari satu dan nol ke dalam biner yang sesuai:

$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin

apa yang dilakukannya:

  • perl -ne akan beralih melalui setiap baris file input yang disediakan di STDIN (instructions.txt )
  • pack("B32", $_)akan mengambil daftar string 32 bit ( $_yang baru saja kita baca dari STDIN), dan mengonversinya menjadi nilai biner (Anda juga dapat menggunakan"b32" jika Anda ingin urutan bit naik di dalam setiap byte alih-alih urutan bit menurun; lihat perldoc -f packuntuk detail lebih lanjut)
  • print kemudian akan mengeluarkan nilai yang dikonversi ke STDOUT, yang kemudian kami arahkan ke file biner kami instructions.bin

memeriksa:

$ 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  ....
Matija Nalis
sumber
8

Menambahkan -ropsi (mode mundur) ke xxd -btidak benar-benar berfungsi sebagaimana dimaksud, karena xxd sama sekali tidak mendukung menggabungkan kedua flag ini (mengabaikan -bjika keduanya diberikan). Sebagai gantinya, Anda harus mengubah bit menjadi hex sendiri terlebih dahulu. Misalnya seperti ini:

( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin

Penjelasan lengkap:

  • Bagian di dalam tanda kurung membuat bcskrip. Pertama-tama mengatur basis input ke biner (2) dan basis output ke heksadesimal (16). Setelah itu, sedperintah mencetak konten instructions.txtdengan tanda titik koma di antara masing-masing kelompok 4 bit, yang sesuai dengan 1 digit hex. Hasilnya disalurkan ke bc.
  • Titik koma adalah pemisah perintah bc, jadi semua skrip yang dilakukan adalah mencetak setiap integer input kembali (setelah konversi basis).
  • Output dari bcadalah urutan digit hex, yang dapat dikonversi ke file dengan biasa xxd -r -p.

Keluaran:

$ 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  ....
nomadictype
sumber
Maaf, masih ada bug endianness dalam hal ini. Bekerja memperbaikinya!
nomadictype
1
Sebenarnya tidak apa-apa. Saya sebelumnya bingung dengan menggunakan lebar keluaran yang salah pada perintah xxd terakhir.
nomadictype
1
Saya telah diuji script dan bekerja tetapi output: (standard_in) 1: syntax error. Dapatkah Anda menjelaskan apa syntax erroryang dimaksud atau mengapa ini terjadi? Apakah ini juga terjadi pada mesin Anda?
dopamane
2

Jawaban asli saya salah - xxdtidak dapat menerima -patau -rdengan -b...

Mengingat bahwa jawaban lain bisa diterapkan, dan untuk kepentingan " cara lain ", bagaimana dengan yang berikut:

Memasukkan

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Keluaran

$ 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

Bash pipeline:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat - tidak perlu, tetapi digunakan untuk kejelasan
  • tr -d $'\n' - hapus semua baris baru dari input
  • read -N 4 nibble- baca persis 4 × karakter ke dalam nibblevariabel
  • printf '%x' "$((2#${nibble}))" mengkonversi nibble dari binary ke 1 × hex karakter
    • $((2#...)) - Konversi nilai yang diberikan dari basis 2 (biner) ke basis 10 (desimal)
    • printf '%x' - memformat nilai yang diberikan dari basis 10 (desimal) ke basis 16 (heksadesimal)
  • xxd -r -p- membalikkan ( -r) dump biasa ( -p) - dari heksadesimal ke biner mentah

Python:

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
  • Heredoc ( ) yang tidak dikutip<< EOF digunakan untuk mendapatkan konten ke dalam kode Python
    • Ini tidak efisien jika inputnya menjadi besar
  • catdan tr- digunakan untuk mendapatkan input (satu baris) yang bersih
  • range(0, len(d), 8) - dapatkan daftar angka dari 0 hingga akhir string d , melangkah 8 × karakter sekaligus.
  • chr(int(d[i:i+8],2))- Konversi irisan saat ini ( d[i:i+8]) dari biner ke desimal ( int(..., 2)), dan kemudian ke karakter mentah ( chr(...))
  • [ x for y in z]- Pemahaman daftar
  • ''.join(...) - Konversi daftar karakter menjadi satu string
  • print(...) - cetak ini
Attie
sumber
1
Catatan: di banyak shell |di akhir baris berfungsi seperti backslash: perintah berlanjut ke baris berikutnya. Dengan cara ini Anda dapat menghilangkan beberapa garis miring terbalik. Saya tidak yakin apakah menggunakan simbol pipa setelah LF adalah keputusan Anda. Saya menyebutkan cara lain jika Anda tidak tahu.
Kamil Maciorowski
1
Saya tidak tahu, terima kasih! Saya suka memecah pipa menjadi garis logis, dan memiliki pipa |(atau pengalihan >, operator boolean &&, dll ...) secara eksplisit di depan untuk visibilitas / kejelasan ... mungkin hal gaya / preferensi.
Attie
1
Setelah beberapa pemikiran saya dapat mulai menggunakan gaya ini karena orang dapat mengetahui dua garis terhubung, dengan memeriksa salah satu dari mereka. Jika |pada akhirnya, baris berikutnya mungkin terlihat seperti perintah mandiri, mungkin membingungkan. Ini sebabnya saya pikir gaya mungkin keputusan Anda.
Kamil Maciorowski
Luar biasa, beri tahu saya caranya :-)
Attie
1
Ini berjalan dengan baik . :)
Kamil Maciorowski
1

Anda juga dapat mencoba memposting ini ke situs CodeGolf SE, tetapi inilah versi alternatif Python saya (hanya untuk tantangan tendangan):

python -c "import sys,struct;[sys.stdout.buffer.write(struct.pack('!i',int(x,2)))for x in sys.stdin]" \
< input.txt > output.bin

Asumsi input.txt berisi data Anda, dan itu diformat hingga 32 karakter per baris.

Ini menggunakan structpaket Python 3 dan menulis / membaca untuk stdin / out. (Dalam Python 2 itu akan lebih pendek).

wvxvw
sumber