바이너리 파일에서 일치하는 두 패턴 사이의 데이터를 추출합니다.

바이너리 파일에서 일치하는 두 패턴 사이의 데이터를 추출합니다.

바이너리 텍스트 파일에서 JPEG 이미지를 추출하려고 합니다. 0xFF 0xD8(이미지 시작)과 0xFF 0xD9(이미지 끝) 사이의 모든 데이터를 추출하고 싶습니다. 이전에는 received.txt라는 단일 단락 파일에서 원하는 image.jpg를 얻기 위해 다음 명령을 성공적으로 실행했습니다.

sed 's/.*\xFF\xD8/\xFF\xD8/; s/\xFF\xD9.*/\xFF\xD9/' received.txt > image.jpg

하지만 다른 파일에 대해 동일한 작업을 실행하려고 하면 작동하지 않습니다. 나도 사용해봤는데

sed -n '/\xFF\xD8/,/\xFF\xD9/p' received.txt > temp.txt
sed 's/.*\xFF\xD8/\xFF\xD8/; s/\xFF\xD9.*/\xFF\xD9/' temp.txt > image.jpg

성공하지 못한 채 일치하는 줄 앞이나 뒤의 줄을 삭제합니다.

파일이 너무 크지만 아래에 관련 부분의 16진수 덤프를 붙여넣었습니다.

0a 55 57 5d 50 cf ff d8 ff fe ff ff ff d9 df 47 fe e7 c9 3b e9 9b 6b 55 c4 57 9b 98 73 fd 15 f7 77 7e f7 95 dd 55 f7 55 05 cc 55 97 55 dd 62 d1 1f 51 ef f1 ef fb e9 bf ed 5f bf f2 9d 75 af fe 6b fb bf 8f f7 f7 7e ff d3 bf 8e d5 5f df 57 75 fe 77 7b bf d7 af df 5d fb 0a 47 de d5 ff c1 23 9b 20 08 20 65 3c 06 83 11 05 30 50 a0 20 55 20 84 41 04 c2 59 50 89 64 44 44 10 05 20 87 28 1d a9

이 경우 원하는 출력의 16진수 덤프는 다음과 같습니다.

ff d8 ff fe ff ff ff d9

고쳐 쓰다

문제를 해결하려고 시도하는 동안 sed 명령이 일치하는 패턴 앞이나 뒤의 모든 문자를 비ASCII 문자(0x80 - 0xFF)까지 제거하지만 그 이상은 제거하지 않는다는 것을 발견했습니다. 예를 들어, 다음과 같이 해보자:

echo 55 57 5d 50 cf 50 65 7f ff d8 ff fe ff ff ff d9 | xxd -r -p | sed 's/.*\xFF\xD8/\xFF\xD8/' > output

출력 16진수 덤프는 다음과 같이 볼 수 있습니다.

xxd output

이것은:

55 57 5d 50 cf ff d8 ff fe ff ff ff d9

보시다시피 비ASCII 문자와 일치하는 패턴 사이의 문자는 삭제되지만 비ASCII 문자 앞의 문자는 삭제되지 않습니다.


대체 솔루션(완벽하지는 않음)

다음 명령을 사용하여 문제를 어느 정도 해결했습니다.

sed 's/\xFF\xD8/\x0A\xFF\xD8/; s/\xFF\xD9/\xFF\xD9\x0A/' received.txt > temp.txt

그런 다음 다음 명령을 실행합니다(0xFF 0xD8과 0xFF 0xD9 사이에 개행 문자(0x0A)가 없는 경우 이 명령이 작동합니다).

sed -n '/\xFF\xD8/{/\xFF\xD9/p}' temp.txt > image.jpg

그러나 image.jpg 파일이 비어 있으면(위 명령을 실행한 후) 다음 명령을 실행하십시오.

sed -n '/\xFF\xD8/,/\xFF\xD9/p' temp.txt > image.jpg

이 명령은 image.jpg 파일의 끝 부분(즉, 0xFF 0xD9 뒤)에 0x0A를 넣는 것을 제외하고 필요한 작업을 수행합니다. 제 경우에는 JPEG 파일이 0xFF 0xD9 마크 이후의 데이터를 자동으로 삭제하기 때문에 문제가 발생하지 않았습니다.

@chaos가 완벽한 솔루션을 제시하는 동안 "이미지 파일이 비어 있는 경우" 조건 구현에 갇혀 있었습니다. 그래서 저는 지금 그의 해결책을 따르고 있습니다. @chaos 정말 감사합니다!


노트:

sed 명령으로 파이프할 수 있는 16진수 덤프에서 실제 데이터를 가져오는 방법은 다음과 같습니다.

echo 0a 55 57 5d 50 cf ff d8 ff fe ff ff ff d9 df 47 fe e7 c9 3b e9 9b 6b 55 c4 57 9b 98 73 fd 15 f7 77 7e f7 95 dd 55 f7 55 05 cc 55 97 55 dd 62 d1 1f 51 ef f1 ef fb e9 bf ed 5f bf f2 9d 75 af fe 6b fb bf 8f f7 f7 7e ff d3 bf 8e d5 5f df 57 75 fe 77 7b bf d7 af df 5d fb 0a 47 de d5 ff c1 23 9b 20 08 20 65 3c 06 83 11 05 30 50 a0 20 55 20 84 41 04 c2 59 50 89 64 44 44 10 05 20 87 28 1d a9 | xxd -r -p

다음을 통해 파일의 16진수 덤프를 볼 수 있습니다.

xxd file.txt

답변1

샘플 데이터 사용 및 grepPCRE(Perl 정규 표현식) 활성화( -P):

grep -oP '\xFF\xD8.*\xFF\xD9' input >image.jpeg

-o플래그는 grep일치하는 부분만 인쇄한다는 의미입니다. 이후 테스트에서는 유망해 보였습니다.

$ file image.jpeg
image.jpeg: JPEG image data

편집하다: 위의 방법이 작동하지 않고 반드시 작동해야 하는 경우 sed데이터를 텍스트로 변환해야 합니다.

hexdump -ve '1/1 "%.2X"' input | sed 's/.*\(FFD8.*FFD9\).*/\1/' | xxd -r -p >image.jpeg
  • 파일은 귀하의 질문과 유사한 시퀀스로 변환됩니다 hexdump.input
    • -e형식 지정
    • 1/11회 형식(반복 횟수)을 적용한 후 각 반복에 대해 해석할 바이트 수(바이트 수)를 1지정함을 나타냅니다./
    • %.2X형식은 두 자리 16진수 값입니다.
  • 그런 다음 덤프 sed전후의 모든 내용을 삭제하십시오 FFD8.FFD9
    • 대괄호는 \(...\)나중에 사용하기 위해 저장하려는 하위 패턴을 지정합니다.
    • \1모든 것을 위 하위 패턴의 내용인 으로 바꿉니다 .
  • 최소한 xxd16진수 덤프를 바이너리 형식으로 되돌리세요.

질문에 있는 예제를 사용하면 테스트가 성공합니다.

$ echo 0a 55 57 5d 50 cf ff d8 ff fe ff ff ff d9 df 47 fe e7 c9 3b e9 9b 6b 55 c4 57 9b 98 73 fd 15 f7 77 7e f7 95 dd 55 f7 55 05 cc 55 97 55 dd 62 d1 1f 51 ef f1 ef fb e9 bf ed 5f bf f2 9d 75 af fe 6b fb bf 8f f7 f7 7e ff d3 bf 8e d5 5f df 57 75 fe 77 7b bf d7 af df 5d fb 0a 47 de d5 ff c1 23 9b 20 08 20 65 3c 06 83 11 05 30 50 a0 20 55 20 84 41 04 c2 59 50 89 64 44 44 10 05 20 87 28 1d a9 | \
  xxd -r -p | \
  hexdump -ve '1/1 "%.2X"' | \
  sed 's/.*\(FFD8.*FFD9\).*/\1/' | \
  xxd -r -p >image.jpeg
$
$ file image.jpeg
image.jpeg: JPEG image data
$ xxd image.jpeg
0000000: ffd8 fffe ffff ffd9                      ........

답변2

@chaos 솔루션에 더 많은 것을 추가하고 싶었습니다.

hexdump -ve '1/1 "%.2X "' input | sed 's/.*\(FF D8.*FF D9\).*/\1/' | xxd -r -p > image.jpeg

방금 %.2Xand 뒤 와 사이에 FFD8공백을 추가했습니다 FFD9. 이는 다음과 같은 이동된 패턴의 일치를 방지하기 위한 것입니다.

0f fd 80 ... 0f fd 90

관련 정보