我有一个文件instructions.txt
,内容如下:
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011
我如何创建instructions.bin
与 相同的数据的二进制文件instructions.txt
。换句话说,.bin
文件应该与文件中的 192 位相同.txt
,每行 32 位。我在 Ubuntu Linux 上使用 bash。我试图使用,xxd -b instructions.txt
但输出比 192 位长得多。
答案1
一行代码将 32 位的 1 和 0 字符串转换为相应的二进制:
$ 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'
- 删除输入中的所有换行符read -N 4 nibble
- 读确切地4× 字符放入nibble
变量中printf '%x' "$((2#${nibble}))"
将半字节从二进制转换为 1× 十六进制字符$((2#...))
- 将给定值从基数 2(二进制)转换为基数 10(十进制)printf '%x'
- 将给定值从十进制(十进制)格式化为十六进制(十六进制)
xxd -r -p
- 反转(-r
)普通转储(-p
)- 从十六进制到原始二进制
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
答案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 上测试