バイナリファイル形式(これらのファイルのインスタンスが多い)があり、「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
。