修补二进制文件中的多个字符串

修补二进制文件中的多个字符串

我有一个二进制文件类型(这些文件的许多实例),我想用“DMC-GX95”替换字符串“DC-GX850”。幸运的是,这两个字符串的长度相等。文件可能有 22MB 大。通常,该字符串在文件中出现两次(在前 1000 个字节内)。两者都需要更换。

我的操作系统是 MacOS 10.14.6,运行标准 BASH。

我有解决方案的两个部分,但我无法将它们组合起来。对于我的测试用例,源文件是P1000047.RW2,修改后的文件是P1000047D.RW2; “44434d2d47583835”是“DMC-GX95”的十六进制表示; 3a4 和 10f0 是该文件实例的字符串开头的文件偏移量;其他文件可能有不同的偏移量。

此代码正确修补文件:

echo "3a4: 44434d2d47583835" | xxd  -r - P1000047D.RW2
echo "10f0: 44434d2d47583835" | xxd  -r - P1000047D.RW2

此代码生成补丁所需的两个字符串:

strings -t x P1000047.RW2 | grep "DC-GX850" | sed s/\ DC-GX850/:\ 44434d2d47583835/

结果:

3a4: 44434d2d47583835
10f0: 44434d2d47583835

但是,当我尝试将两者结合起来时,此代码仅执行第一个补丁

strings -t x P1000047.RW2 | grep "DC-GX850" | sed s/\ DC-GX850/:\ 44434d2d47583835/ | xxd  -r - P1000047D.RW2

我尝试过使用 sed 和 -n 选项,但仍然无法让它工作。

我当然可以将脚本编写为循环,但如果可能的话我想避免这种情况。有什么建议么?

答案1

只需使用perl它即可轻松处理二进制文件:

perl -pi -e 's/DC-GX850/DMC-GX95/g' ./*.RW2

或者,如果您只想在文件的前 1000 个字节中进行替换:

perl -pi -e '
  BEGIN {$/ = \1000} # records are 1000 byte blocks instead of lines
  s/DC-GX850/DMC-GX95/g if $. == 1; # substitute in first record only
  close ARGV if eof # to reset $. between files' ./*.RW2

使用-i,文件被就地修改(实际上,被修改后的副本替换),更改为以-i.orig保留带有扩展名的原始文件.orig

相关内容