如何在 Bash 中制作具有特定十六进制模式的文件?

问题描述 投票:0回答:4

我正在尝试在 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 ....

我应该修复哪一点?

bash dd
4个回答
1
投票

你可以使用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
...

1
投票

在小端

printf '\x34\x12\x78\x56%.0s' {1..10} > File.bin

1
投票

另一种解决方案是使用

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

0
投票

您的

tr
尝试未能成功的原因有多种。

  • $'\x12345678'
    指定字符
    '\x12'
    后跟文字字符串
    '345678'
    。我猜你希望制作出
    '\x12\x34\x56\x78'
  • tr
    的第二个参数比第一个参数长时,多余的字符将被忽略。 (您无法通过根据需要多次重复
    \000
    来解决这个问题;然后
    tr
    将忽略较早的实例,并为该角色的所有实例使用最后一个实例!因此
    tr '\000\000\000\000' abcd
    相当于
    tr '\000' d
© www.soinside.com 2019 - 2024. All rights reserved.