我正在尝试在 Bash 中使用特定的 4 字节十六进制模式制作许多文件(4KB~10MB)。
例如:
0000000: 1234 5678 1234 5678 1234 5678 1234 5678 ....
所以我使用
dd
制作了零模式数据,并将其转换为特定的 4 字节十六进制模式,如下所示
dd if=/dev/zero bs=1k count=10 | tr "\000" $'\x12345678' > File.bin
但它仅返回给定十六进制模式的前 1 个字节。
0000000 : 1212 1212 1212 1212 1212 1212 1212 1212 ....
我应该修复哪一点?
你可以使用perl
$ dd if=/dev/zero bs=1k count=10 | perl -0777 -pe "s/\x00{4}/\x12\x34\x56\x78/g" > file.bin
$ xxd file.bin
0000000: 1234 5678 1234 5678 1234 5678 1234 5678 .4Vx.4Vx.4Vx.4Vx
0000010: 1234 5678 1234 5678 1234 5678 1234 5678 .4Vx.4Vx.4Vx.4Vx
...
在小端
printf '\x34\x12\x78\x56%.0s' {1..10} > File.bin
yes
yes $'\x12\x34\x56\x78' | tr -d '\n' | head -c 10240
如果你有GNU头你也可以直接指定大小后缀如4MB,10M...
$ yes $'\x12\x34\x56\x78' | tr -d '\n' | head -c 4kB | hexdump -C
00000000 12 34 56 78 12 34 56 78 12 34 56 78 12 34 56 78 |.4Vx.4Vx.4Vx.4Vx|
*
00000fa0
jot
。例如,以下命令将生成 4K 输出
jot -s "" -b $'\x12\x34\x56\x78' 4096
性能对比:目前的解决方案中
yes
+ GNU tr
是最快的,可以达到每秒数百MB
在 Linux 上:
$ time dd if=/dev/zero bs=300M count=1 2>/dev/null | perl -0777 -pe "s/\x00{4}/\x12\x34\x56\x78/g" >/dev/null
real 0m4.714s
user 0m4.416s
sys 0m0.395s
$ time jot -s "" -b $'\x12\x34\x56\x78' $((300*1024*1024)) >/dev/null
real 0m13.486s
user 0m13.330s
sys 0m0.152s
$ time yes $'\x12\x34\x56\x78' | tr -d '\n' | head -c 300M >/dev/null
real 0m0.373s
user 0m0.227s
sys 0m0.556s
在 macOS 上我尝试了 BSD 工具和 GNU 工具(前缀为
g
),可以看到 BSD 工具相当糟糕
$ time yes $'\x12\x34\x56\x78' | tr -d '\n' | ghead -c 300M >/dev/null
yes $'\x12\x34\x56\x78' 0.03s user 0.20s system 0% cpu 27.792 total
tr -d '\n' 27.71s user 0.07s system 99% cpu 27.791 total
ghead -c 300M > /dev/null 0.16s user 0.24s system 1% cpu 27.788 total
$ time gyes $'\x12\x34\x56\x78' | tr -d '\n' | ghead -c 300M >/dev/null
gyes $'\x12\x34\x56\x78' 0.15s user 0.30s system 1% cpu 27.997 total
tr -d '\n' 27.92s user 0.07s system 99% cpu 27.995 total
ghead -c 300M > /dev/null 0.16s user 0.25s system 1% cpu 27.992 total
$ time yes $'\x12\x34\x56\x78' | gtr -d '\n' | ghead -c 300M >/dev/null
yes $'\x12\x34\x56\x78' 0.02s user 0.46s system 46% cpu 1.013 total
gtr -d '\n' 0.51s user 0.42s system 92% cpu 1.012 total
ghead -c 300M > /dev/null 0.14s user 0.17s system 30% cpu 1.011 total
$ time gyes $'\x12\x34\x56\x78' | gtr -d '\n' | ghead -c 300M >/dev/null
gyes $'\x12\x34\x56\x78' 0.13s user 0.44s system 66% cpu 0.855 total
gtr -d '\n' 0.48s user 0.33s system 95% cpu 0.854 total
ghead -c 300M > /dev/null 0.13s user 0.16s system 34% cpu 0.852 total
$ time jot -s "" -b $'\x12\x34\x56\x78' $((300*1024*1024)) >/dev/null
jot -s "" -b $'\x12\x34\x56\x78' $((300*1024*1024)) > /dev/null 38.22s user 0.04s system 99% cpu 38.270 total
$ time dd if=/dev/zero bs=300M count=1 2>/dev/null | perl -0777 -pe "s/\x00{4}/\x12\x34\x56\x78/g" >/dev/null
dd if=/dev/zero bs=300M count=1 2> /dev/null 0.00s user 0.20s system 51% cpu 0.392 total
perl -0777 -pe "s/\x00{4}/\x12\x34\x56\x78/g" > /dev/null 4.26s user 0.34s system 96% cpu 4.739 total
您的
tr
尝试未能成功的原因有多种。
$'\x12345678'
指定字符 '\x12'
后跟文字字符串 '345678'
。我猜你希望制作出'\x12\x34\x56\x78'
?tr
的第二个参数比第一个参数长时,多余的字符将被忽略。
(您无法通过根据需要多次重复 \000
来解决这个问题;然后 tr
将忽略较早的实例,并为该角色的所有实例使用最后一个实例!因此 tr '\000\000\000\000' abcd
相当于 tr '\000' d
)