конвертувати текстовий файл бітів у двійковий файл


12

У мене є файл instructions.txtіз вмістом:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Як я можу створити двійковий файл instructions.binз тих же даних, що і instructions.txt. Іншими словами, .binфайл повинен бути тим самим 192 біта, який є у .txtфайлі, з 32 бітами на рядок. Я використовую bash на Ubuntu Linux. Я намагався використовувати, xxd -b instructions.txtале вихід набагато довший, ніж 192 біти.

Відповіді:


6

oneliner для перетворення 32-бітових рядків одиниць і нулів у відповідні двійкові:

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

що це робить:

  • perl -neбуде повторюватися через кожен рядок вхідного файлу, наданого на STDIN ( instructions.txt)
  • pack("B32", $_)візьме рядковий рядок із 32 біт ( $_який ми щойно прочитали зі STDIN) та перетворить його у бінарне значення (ви також можете використати, "b32"якщо хочете висхідний бітовий порядок всередині кожного байту замість низхідного порядку біт; див. perldoc -f packдокладніше)
  • print Потім виведе це перетворене значення в STDOUT, яке ми перенаправляємо на наш двійковий файл instructions.bin

перевірити:

$ 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

Додавання -rпараметра (режим зворотного зв'язку) до xxd -bнасправді не працює за призначенням, оскільки xxd просто не підтримує комбінування цих двох прапорів (він ігнорує, -bякщо надано обидва). Натомість ви повинні спочатку перетворити біти в шістнадцятковий. Наприклад так:

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

Повне пояснення:

  • Частина всередині дужок створює bcсценарій. Він спочатку встановлює вхідну базу двійковою (2), а вихідну базу - шістнадцятковою (16). Після цього sedкоманда друкує вміст instructions.txtкрапкою з комою між кожною групою з 4 біт, що відповідає 1 шістнадцятковій цифрі. Результат вкладається в bc.
  • Точка з комою є роздільником команд bc, тому все сценарій - це друк кожного зворотного цілого числа назад (після базового перетворення).
  • Виведенням bcє послідовність шістнадцяткових цифр, які можна перетворити у файл із звичайними xxd -r -p.

Вихід:

$ 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

1
Насправді це добре. Раніше мене плутали, використовуючи неправильну вихідну ширину в останній команді xxd.
nomadictype

1
Я перевірив сценарій і він працює , але виходи: (standard_in) 1: syntax error. Чи можете ви пояснити, на що syntax errorйдеться чи чому це відбувається? Чи трапляється це і на вашій машині?
допаман

2

Моя оригінальна відповідь була неправильною - xxdне можу прийняти ні з, -pні -rз -b...

З огляду на те, що інші відповіді працездатні, і в інтересах " іншого шляху ", як щодо наступного:

Вхідні дані

$ 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

Баш трубопровід:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat - непотрібні, але використовуються для наочності
  • tr -d $'\n' - видаліть всі нові рядки із вхідних даних
  • read -N 4 nibble- читати рівно 4 × символів у nibbleзмінну
  • printf '%x' "$((2#${nibble}))" перетворити кусок з двійкового в 1 × шестигранний символ
    • $((2#...)) - перетворити задане значення з бази 2 (двійкове) в базу 10 (десятковий)
    • printf '%x' - відформатувати задане значення від базової 10 (десятковий) до бази 16 (шістнадцятковий)
  • xxd -r -p- зворотний ( -r) звичайний дамп ( -p) - від шістнадцяткової до сирої двійкової

Пітон:

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) використовується для отримання вмісту в код Python
    • Це не ефективно, якщо вхід стає великим
  • catі tr- використовується для отримання чистого (однорядного) вводу
  • range(0, len(d), 8)- отримати список чисел від 0 до кінця рядка d, наступаючи 8 × символів за один раз.
  • chr(int(d[i:i+8],2))- перетворити поточний фрагмент ( d[i:i+8]) з двійкового в десятковий ( int(..., 2)), а потім у необроблений символ ( chr(...))
  • [ x for y in z]- осмислення списку
  • ''.join(...) - перетворити список символів в один рядок
  • print(...) - роздрукуйте

1
Примітка: у багатьох оболонках |в кінці рядка працює як зворотний косий рядок: команда продовжується до наступного рядка. Таким чином можна позбутися від декількох відхилень. Я не впевнений, чи використання символів труби після НЧ було вашим усвідомленим рішенням. Я згадую інший спосіб, якщо ви цього не знали.
Каміль Маціоровський

1
Я не знав, дякую! Мені подобається розбивати конвеєр на логічні лінії та мати труби |(або переадресації >, булеві оператори &&тощо) явно спереду для наочності / чіткості ... можливо, стилістична / переважна річ.
Attie

1
Після деяких думок я можу почати використовувати цей стиль, тому що можна сказати, що два рядки пов'язані, вивчивши будь-яку з них. Якщо |в кінці, наступний рядок може виглядати як окрема команда, це може бути заплутано. Ось чому я подумав, що стиль може бути вашим усвідомленим рішенням.
Каміль Маціоровський

Дивовижно, дайте мені знати, як це йде :-)
Attie


1

Ви також можете спробувати опублікувати це на сайті CodeGolf SE, але ось моя альтернативна версія Python (лише для виклику):

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

Припустимо, що input.txtмістить ваші дані, і вона відформатована до 32 символів на рядок.

Для цього використовується structпакет Python 3 та запис / читання для зменшення / виходу. (У Python 2 це було б коротше).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.