内容の入ったファイルinstructions.txt
があります。
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
instructions.bin
と同じデータのバイナリファイルinstructions.txt
を作成するにはどうすればいいですか。言い換えれば、.bin
ファイルは、.txt
ファイルにあるのと同じ192ビットで、1行あたり32ビットであるべきです。私はUbuntu Linux上でbashを使用しています。私はxxd -b instructions.txt
を使用しようとしていましたが、出力は192ビットよりずっと長いです。
1と0の32ビット文字列を対応するバイナリに変換するoneliner:
$ 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 ....
-r
にxxd -b
オプション(リバースモード)を追加しても、実際には意図したとおりには機能しません。xxdはこれら2つのフラグの組み合わせをサポートしていないためです(両方が指定されている場合-b
は無視されます)代わりに、まず自分でビットを16進数に変換する必要があります。例えばこんな感じ:
( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin
詳しい説明:
bc
スクリプトを作成します。最初に入力基数を2進数(2)に、出力基数を16進数(16)に設定します。その後、sed
コマンドは、4ビットの各グループの間にセミコロンを入れてinstructions.txt
の内容を出力します。これは1つの16進数に対応します。結果はbc
にパイプされます。bc
内のコマンド区切り文字なので、すべてのスクリプトは(整数変換後に)すべての入力整数を出力します。bc
の出力は一連の16進数で、通常の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 ....
私の 元の答え は正しくありませんでした - 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'
- 入力からすべての改行を削除read -N 4 nibble
- 正確に4×文字をnibble
変数に読み込むprintf '%x' "$((2#${nibble}))"
ニブルを2進数から1×16進数文字に変換します$((2#...))
- 与えられた値を2進数(2進数)から10進数(10進数)に変換するprintf '%x'
- 与えられた値を基数10(10進数)から基数16(16進数)の範囲でフォーマットします。xxd -r -p
- プレーンダンプ(-r
)を反転(-p
) - 16進数から生のバイナリに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
<< EOF
)は、Pythonコードにコンテンツを入れるために使用されますcat
とtr
- きれいな(1行の)入力を得るために使われますrange(0, len(d), 8)
- 0から文字列d
の終わりまでの数値のリストを取得します。chr(int(d[i:i+8],2))
- 現在のスライス(d[i:i+8]
)を2進数から10進数(int(..., 2)
)、次に生の文字(chr(...)
)に変換します[ x for y in z]
- リスト内包表記''.join(...)
- 文字のリストを単一の文字列に変換するprint(...)
- 印刷するこれを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
にあなたのデータが含まれていて、それが1行につき32文字にフォーマットされていると仮定します。
これはPython 3のstruct
パッケージとstdin/outへの読み書きを使います。 (Python 2ではもっと短くなったでしょう)。