
У меня есть файл instructions.txt
с содержимым:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
Как мне создать двоичный файл instructions.bin
с теми же данными, что и instructions.txt
. Другими словами, .bin
файл должен быть таким же 192 битами, как и в .txt
файле, с 32 битами на строку. Я использую bash на Ubuntu Linux. Я пытался использовать, xxd -b instructions.txt
но вывод намного длиннее 192 бит.
решение1
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 ....
решение2
Добавление -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 ....
решение3
Мойоригинальный ответбыл неверен - 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
Конвейер Bash:
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'
- remove all newlines from the inputread -N 4 nibble
- читатьточно4× символа вnibble
переменнуюprintf '%x' "$((2#${nibble}))"
преобразовать полубайт из двоичного в шестнадцатеричный символ 1×$((2#...))
- преобразовать заданное значение из двоичной системы счисления в десятичную систему счисленияprintf '%x'
- отформатировать заданное значение из десятичной системы счисления в шестнадцатеричную систему счисления
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(...)
- распечатать это
решение4
Двоичные файлы не разделяют строки символами новой строки. Двоичные файлы не имеют разделителей; это просто один файл с кучей 0 и 1, хранящийся на каком-то устройстве, организованном в секторах, контролируемых таблицей размещения файлов или аналогичным отображением, чтобы придать ему смысл.
Вы можете либо преобразовать текстовый файл в двоичный формат, получив в результате 192 бита (24 байта), либо добавить символ новой строки после каждой 32-битной последовательности, чтобы получить файл с 6 дополнительными байтами.
Код ниже даст вам 192-битный файл, как и требовалось:
for x in $(cat file.txt);
do s=${x:0:32};
echo $(printf '%08X' "$((2#$s))");
done | xxd -r -p > file.bin
Альтернативой является чтение 8 бит за раз, если не нужен дополнительный код для заполнения (4-байтовые строки в текстовом файле).
Протестировано на Ubuntu 16.04.7