bit metin dosyasını ikili dosyaya dönüştür


10

instructions.txtİçeriği olan bir dosya var :

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

instructions.binAynı verilerle ikili bir dosyayı nasıl oluşturabilirim instructions.txt. Başka bir deyişle, .bindosya , dosyadaki 192 bit, .txtsatır başına 32 bit olmalıdır. Ubuntu Linux'ta bash kullanıyorum. Kullanmaya çalışıyordum xxd -b instructions.txtama çıktı 192 bitden daha uzun.

Yanıtlar:


5

onbir ve 32 bitlik dizgileri ve sıfırları karşılık gelen ikili dosyaya çevirir:

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

bu ne yapar:

  • perl -neSTDIN ( instructions.txt) 'de sağlanan her giriş dosyası satırı boyunca yinelenir
  • pack("B32", $_)32 bitlik bir dizge listesi alacaktır ( $_STDIN'den yeni okuduk) ve onu ikili değere dönüştürecektir (alternatif olarak "b32", azalan bit sırası yerine her bir bayt içinde bit sırası istemek için kullanabilirsiniz ; perldoc -f packdaha fazla bilgi için bakınız)
  • print daha sonra ikili dosyamıza yönlendirdiğimiz bu değeri STDOUT'a dönüştürür. instructions.bin

DOĞRULAYIN:

$ 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  ....

8

Seçeneğe -r(ters mod) eklemek xxd -baslında amaçlandığı gibi çalışmaz, çünkü xxd bu iki bayrağın birleştirilmesini desteklemez ( -bher ikisi de verildiyse dikkate almaz ). Bunun yerine, önce kendiniz bitleri hex'e dönüştürmeniz gerekir. Örneğin böyle:

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

Tam açıklama:

  • Parantez içindeki kısım bir bcsenaryo oluşturur . Öncelikle giriş tabanını ikili (2) ve çıkış tabanını onaltılık (16) olarak ayarlar. Bundan sonra sedkomut, instructions.txther bir 4 bitlik grup arasında 1 altıgen basamağa karşılık gelen bir noktalı virgül içeriğini yazdırır . Sonuç boruya aktarılır bc.
  • Noktalı virgül bir komut ayırıcıdır bc, bu nedenle tüm komut dosyası her giriş tamsayısını geri yazdırır (temel dönüştürmeden sonra).
  • Çıktısı bc, normal bir dosyaya dönüştürülebilen onaltılık basamak dizisidir xxd -r -p.

Çıktı:

$ 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  ....

Üzgünüz, bu konuda hala bir endianness hatası var. Tamir etmeye çalışıyor!
göçebe türü

1
Aslında, sorun değil. Son xxd komutunda yanlış çıkış genişliğini kullanarak kafam karışmıştı.
göçebe tipi

1
Senaryoyu test ettik ve onu çıkışlar ancak çalışır: (standard_in) 1: syntax error. syntax errorBunun ne anlama geldiğini veya bunun neden olduğunu açıklayabilir misiniz ? Bu da makinende oluyor mu?
dopamane

2

Benim asıl cevap yanlıştı - xxdYa kabul edemez -pya da -rbirlikte -b...

Diğer cevapların uygulanabilir olduğunu ve “ başka bir şekilde ” çıkarsa, aşağıdakilere ne dersiniz:

Giriş

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Çıktı

$ 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 boru hattı:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat - Gereksiz, ancak netlik için kullanılır
  • tr -d $'\n' - tüm yeni satırları girişten kaldır
  • read -N 4 nibble- değişkene tam 4 × karakter okunibble
  • printf '%x' "$((2#${nibble}))" ucu ikilikten 1 × hex karaktere dönüştürün
    • $((2#...)) - verilen değeri taban 2'den (ikili) taban 10'a (ondalık) dönüştürün
    • printf '%x' - verilen değeri taban 10'dan (ondalık) taban 16'ya (onaltılık) biçimlendirin
  • xxd -r -p- reverse ( -r), düz bir dökümü ( -p) - onaltılıktan ham ikiliye

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
  • Tırnak içine alınmamış heredoc ( << EOF) Python koduna içeriği almak için kullanılır
    • Giriş büyük olursa bu etkili olmaz
  • catve tr- temiz (tek satırlık) bir girdi elde etmek için kullanılır
  • range(0, len(d), 8)- 0'dan dize kadar olan sayıları içeren bir liste alın dve her seferinde 8 × karakter atlayın.
  • chr(int(d[i:i+8],2))- geçerli dilimi ( d[i:i+8]) ikiliden ondalık ( int(..., 2)) ve daha sonra ham bir karaktere ( chr(...)) dönüştürür
  • [ x for y in z]- liste anlama
  • ''.join(...) - karakter listesini tek bir dizgeye dönüştür
  • print(...) - yazdır

1
Not: |Bir satırın sonundaki birçok kabukta ters eğik çizgi gibi çalışır: komut bir sonraki satıra devam eder. Bu şekilde birkaç ters eğik çizgiden kurtulabilirsiniz. LF'den sonra boru sembollerinin kullanılmasının sizin kararınız olduğuna emin değilim. Bilmiyorsan diye diğer yoldan bahsediyorum.
Kamil Maciorowski

1
Bilmiyordum, teşekkürler! Boru hattını mantıksal hatlara bölmeyi ve boruların |(veya yönlendirmeler >, boolean operatörleri &&, vb ...) açıkça görünürlük / netlik için açık bir şekilde olmasını istiyorum ... belki de stilistik / tercihli bir şey.
Attie

1
Bazı düşüncelerden sonra, bu stili kullanmaya başlayabilirim, çünkü herhangi biri incelenerek iki hattın birbirine bağlı olduğu söylenebilir . Eğer |sonunda, bir sonraki satır başına bir komutla gibi görünebilir, bu kafa karıştırıcı olabilir. Bu yüzden tarzın bilgili kararın olabileceğini düşündüm.
Kamil Maciorowski

Awesome, nasıl gideceğini bilmeme izin ver :-)
Attie

1
Gittiği gibi iyi . :)
Kamil Maciorowski

1

Bunu CodeGolf SE sitesine göndermeyi de deneyebilirsiniz, ancak işte alternatif Python versiyonum (sadece vuruş için):

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

Varsayalım input.txtverilerinizi içerir ve satır başına 32 karaktere biçimlendirilir.

Bu, Python 3 structpaketini ve yazı yazma / okuma yöntemini kullanır . (Python 2'de daha kısa olurdu).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.