我有一个二进制文件类型(这些文件的许多实例),我想用“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
。