바이너리 파일 형식(이러한 파일의 인스턴스가 많음)이 있고 "DC-GX850" 문자열을 "DMC-GX95"로 바꾸고 싶습니다. 다행히 두 문자열의 길이는 동일합니다. 파일 크기는 22MB일 수 있습니다. 일반적으로 이 문자열은 파일에 두 번 나타납니다(처음 1000바이트 내에서). 둘 다 교체해야 합니다.
내 운영 체제는 표준 BASH를 실행하는 MacOS 10.14.6입니다.
솔루션의 두 부분이 있지만 이를 결합할 수는 없습니다. 내 테스트 사례의 경우 소스 파일은 P1000047D.RW2이고 수정된 파일은 P1000047D.RW2입니다. "44434d2d47583835"는 "DMC-GX95"의 16진수 표현이고 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
.