バイナリによる複数の文字列パッチ

バイナリによる複数の文字列パッチ

バイナリファイル形式(これらのファイルのインスタンスが多い)があり、「DC-GX850」文字列を「DMC-GX95」に置き換えたいと思います。幸い、2つの文字列の長さは同じです。ファイルサイズは22MBです。通常、この文字列はファイルに2回表示されます(最初の1000バイト以内)。両方とも交換する必要があります。

私のオペレーティングシステムは、標準のBASHを実行しているMacOS 10.14.6です。

ソリューションの2つの部分がありますが、それらを組み合わせることはできません。私のテストケースでは、ソースファイルはP1000047D.RW2で、変更されたファイルはP1000047D.RW2です。 「44434d2d47583835」は「DMC-GX95」の16進表現で、10f0はそのファイルインスタンスの文字列の先頭です。 ;他のファイルは異なるオフセットを持つことができます。

このコードはファイルを正しくパッチします。

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

このコードはパッチに必要な2つの文字列を生成します。

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

結果:

3a4: 44434d2d47583835
10f0: 44434d2d47583835

しかし、これらの2つを組み合わせようとすると、このコードは最初のパッチのみを実行します。

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

おすすめ記事