와일드카드를 사용하여 16진수 패턴을 찾는 방법은 무엇입니까?

와일드카드를 사용하여 16진수 패턴을 찾는 방법은 무엇입니까?

파일에서 16진수 패턴의 오프셋을 찾으려고 합니다. 이는 특정 값에 대해 작동합니다.

$ grep -obUaP -m1 "\x00\x50\x53\x46\x01\x01\x00\x00\x34\x01\x00\x00" file.bin
3088:PSF4

그러나 이 패턴에는 변경되는 일부 바이트가 포함되어 있으므로 grep에 와일드카드를 포함해야 합니다. 나는 무엇을 해야할지 모르겠습니다. 지금까지 시도한 모든 것은 다음과 같습니다.

  • \x.., \x., ..,내가 생각할 수 있는 모든 유사한 형태는 일치하지 않습니다.
  • \x[0-9][0-9]불일치
  • \x.*불일치
  • 그냥 .*(즉, \x00.*\x01)하다일치하지만 욕심이 많고 패턴 일치 이상의 기능을 수행합니다.

아마도 어리석은 것을 간과하고 있을지 모르지만 여기서 벽에 부딪혔습니다.

16진수 와일드카드를 어떻게 지정합니까, 아니면 최소한 grep 및 perl-regex를 사용하여 16진수를 검색할 때입니까?

답변1

grep -P '\xAB'찾고 있지 않음16진수 문자. 그와 같은 일은 없다16진수 문자. \xABPCRE입니다통사론16진수(10진수 171)에서 코드 포인트 값 0xAB가 있는 문자를 일치시킵니다.

코드 포인트이는 UTF-8을 사용하는 로케일의 유니코드 코드 포인트이고 단일 바이트 문자 세트를 사용하는 로케일의 바이트 값입니다(GNU는 grep -PUTF-8 이외의 멀티바이트 문자 세트를 지원하지 않습니다).

따라서 \xABUTF-8 로케일(2바이트: 0xc2 및 0xab로 인코딩됨)의 U+00AB 문자(<)와 단일 바이트 로케일의 0xAB 바이트(예: Ћiso8859-5 사용을 의미 )와 일치합니다. 문자 집합).

바이트 값을 일치시키려면 로캘이 단일 바이트 문자 집합을 사용하는지 확인해야 합니다. C로캘이 가장 좋은 방법일 것입니다.

LC_ALL=C grep -P '\xAB'

문자 집합에서 나타내는 문자(있는 경우)에 관계없이 0xAB(171) 바이트와 일치합니다.

단일 바이트를 일치시키려면 다시 사용할 수 있습니다 .(C 로케일 또는 문자 세트가 문자당 단일 바이트인 로컬 언어를 가정).

@Angle115가 이미 말한 대로 바이트 값 범위와 일치합니다. ( [\x01-\x45]이는 1에서 0x45/69까지의 바이트 값에 적용됩니다.)

하지만 기억해, grep매칭콘텐츠텍스트철사¹이므로 줄 바꿈 문자를 줄 구분 기호로 찾지 않으며 해당 값은 로케일에 관계없이 항상 0x0A²(10진수 10)입니다.

따라서 LC_ALL=C grep -P '\x23.\xab'3바이트의 시퀀스가 ​​일치하며 첫 번째 바이트의 값은 0x23이고 두 번째 바이트의 값은 any value입니다.0xA 제외세 번째 값은 0xAB입니다.

임의의 값(0xA 포함)이 있는 바이트를 검색하려면 이전처럼 한 번에 한 줄씩 처리하거나 널로 구분된 레코드를 처리하는 것이 아니라 전체 입력을 전체적으로 처리해야 합니다 grep.

이를 수행하려면 플래그(새 줄은 특별히 처리되지 않음 ) 또는 후루룩 모드와 함께 (여러 줄) 옵션을 pcregrep사용할 수 있습니다.-M(?s).perl

LC_ALL=C pcregrep --file-offsets -Ma '(?s)\x23.\xab' < file

( 옵션이 pcregrep없으면 오프셋과 길이를 최대한 가깝게 인쇄합니다.)-b--file-offsets

perl -l -0777 -ne 'print "$-[0]:$_" while /\x23.\xab/gs' < file

또는:

perl -l -0777 -ne 'print $-[0] if /\x23.\xab/s' < file

일치하는 첫 번째 바이트 오프셋만 인쇄됩니다.

perl전체 파일을 메모리에 로드하는 것은 pcregrep불가능하지만 0xA 바이트 떨어진 파일을 처리하지 못하게 하는 내부 제한이 있습니다.


--null¹ 또는 /로 구분된 NUL 레코드-z

¹ ASCII 기반 시스템에서. 나는 libpcre가 EBCDIC 시스템으로 포팅되었는지조차 모르고, 현재 많은 사람들이 이러한 시스템을 접하게 될지도 의심스럽습니다.

답변2

와일드카드를 사용하는 대신 다음과 같이 모든 ASCII 문자와 일치하는 범위를 포함할 수 있습니다.

grep -Pe '\x00\x50\x53\x46[\x00-\x7F]\x01\x00\x00\x34\x01\x00\x00'

관련 정보