ビットのテキストファイルをバイナリファイルに変換する

ビットのテキストファイルをバイナリファイルに変換する

instructions.txt以下の内容のファイルがあります:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

instructions.binと同じデータのバイナリ ファイルを作成するにはどうすればよいでしょうかinstructions.txt。言い換えると、.binファイルはファイルと同じ 192 ビットで.txt、1 行あたり 32 ビットである必要があります。私は Ubuntu Linux で bash を使用しています。使用しようとしましたxxd -b instructions.txtが、出力が 192 ビットよりはるかに長くなります。

答え1

1 と 0 の 32 ビット文字列を対応するバイナリに変換するワンライナー:

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

機能:

  • perl -neSTDINに与えられた入力ファイルの各行を反復処理します(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 がこれら 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は の内容を、instructions.txt1 つの 16 進数に対応する 4 ビットの各グループの間にセミコロンを付けて出力します。結果は にパイプされますbc
  • セミコロンは 内のコマンド区切り文字なのでbc、スクリプトが行うことはすべて、入力されたすべての整数を(基数変換後に)出力するだけです。
  • の出力はbc16 進数のシーケンスであり、通常の を使用してファイルに変換できます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'- 入力からすべての改行を削除します
  • read -N 4 nibble- 読むその通りnibble変数に4文字を入れる
  • 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 << 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。一度に 8 文字ずつ進みます。
  • chr(int(d[i:i+8],2))- 現在のスライス ( d[i:i+8]) を 2 進数から 10 進数 ( int(..., 2)) に変換し、次に生の文字 ( chr(...))に変換します。
  • [ x for y in z]-リストの理解
  • ''.join(...)- 文字のリストを単一の文字列に変換する
  • print(...)- 印刷する

答え4

バイナリ ファイルでは、改行文字で行を区切ることはできません。バイナリ ファイルには区切り文字がありません。バイナリ ファイルは、一連の 0 と 1 を含む 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でテスト済み

関連情報