
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 -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 がこれら 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.txt
1 つの 16 進数に対応する 4 ビットの各グループの間にセミコロンを付けて出力します。結果は にパイプされます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 ....
答え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でテスト済み