grep -ao ...word file.bin
나는 종종 텍스트 내용("단어")과 그 앞에 있는 몇 가지 주의 사항을 찾는 데 사용합니다 .
-a, --text
Process a binary file as if it were text; this is equivalent to the --binary-files=text option.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each such part on a separate
output line.
맞습니다. 이제 막 다음과 같이 동작한다는 것을 깨달았습니다. 먼저 문자열 war
과 그 앞에 있는 문자 하나를 찾으려고 합니다.
$ grep -ao .war myfile.zip
/war
9war
$war
ʆwar
좋아요, 여기에서 4번의 클릭이 발생했습니다. 이제 문자열 war
과 그 앞의 두 문자를 찾으려면 다음을 수행하십시오 .
$ grep -ao ..war myfile.zip
>$war
그러면 이제 어떤 이유에서인지 결과가 하나만 표시됩니까? !
내 생각엔 3개가 누락된 경우 "처음 두 문자"의 값은 0x00(C 문자열의 끝)이므로 grep
해당 일치 항목은 출력되지 않을 것입니다. 그렇지 않으면 여전히 4개의 결과가 나올 것으로 예상됩니다(예를 들어 이전 첫 번째 일치 항목은 파일의 시작 부분에 있습니다. 그렇지 않으면 3개의 결과를 얻게 됩니다.
grep
일치 항목에서 null 바이트를 단순히 "무시"(또는 점 등으로 대체)하고 이를 포함할 수 있는 일치 항목을 계속 인쇄하도록 설득할 수 있습니까 ? 그렇지 않은 경우 grep
이를 수행할 수 있는 다른 도구가 있습니까?
답변1
귀하의 접근 방식에는 적어도 두 가지(바람직하게는 세 가지)의 문제가 있습니다.
non-standard 를 사용하는 경우에도 라인 기반 -o
입니다 grep
. 각 라인의 출력과 일치하는 모든 항목을 찾기 때문입니다 o
. 이는 줄 바꿈으로 구분된 문자 시퀀스입니다(ASCII 기반 시스템에서 값이 10/0x0a인 바이트).
그래서:
grep -o ..war
war
2 이후의 인스턴스 만 반환됩니다.수치(여기서 세 가지 문제 중 하나인 바이트가 아님) 줄 바꿈을 제외하고.
예를 들어 유사한 입력에서 <0x0a>Xwar
0x0a 바이트는 이전 줄을 구분하고 다음 줄은 Xwar
이전에 단 한 문자였던 곳에서 시작됩니다 war
.
UTF-8 로케일에서는 유사한 입력에서 <0xff><0xc3><0xa9>war
2바이트가 문자를 <0xc3><0xa9>
형성 é
하지만 앞의 0xff 바이트는 유효하지 않으므로 문자를 형성할 수 없습니다.
grep
grep
일반적으로 텍스트에서만 작동하므로 구현에 따라 NUL 문자나 지나치게 긴 줄 또는 줄바꿈으로 끝나지 않는 입력으로 작업하면 문제가 발생할 수 있습니다.
그런 다음 에서 xxwarwar
발견 grep -o
되지만 xxwar
더 많은 일치 항목에 대한 검색이 계속되므로 찾을 수 없습니다 arwar
.
이러한 문제는 다음 방법을 사용하여 해결할 수 있습니다 perl
.
perl -l -0777 -ne 'print "$1$2" while m{(?<=(..))(war)}sg'
war
인스턴스 앞의 2바이트(사용자 로케일의 문자가 아님)를 찾고 , 입력 소비를 방지하기 위해 이러한 앞의 바이트에 역방향 연산자를 사용합니다. 레코드 구분 기호를 불가능한 것으로 설정하는 를 사용하여 -0777
입력의 각 줄 대신 전체 입력을 처리합니다.
답변2
또 다른 방법은 바이너리를 16진수로 변환하여 일치시키는 것입니다.
hexdump -v -e '/1 "%02X" " "' file.bin | grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')"
string 앞에 일치시키려는 모든 바이트에 대해 ..
하나씩 필요합니다 . .
단점은 grep이나 Perl의 직접 일치보다 느리고 warwar
Perl 솔루션처럼 연속적인 패턴에서 후속 일치 항목을 찾지 못한다는 것입니다.
결과는 16진수 값으로 인쇄됩니다. 결과를 문자열로 인쇄하려면 다음과 같이 바이트를 다시 변환하십시오.
hexdump -v -e '/1 "%02X" " "' file.bin | \
grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')" | \
xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash
그러나 앞에 문자열과 다른 많은 제어 문자가 \n
있으면 출력이 엉망이 될 수 있습니다.\r
각 바이트 뒤에 공백을 인쇄하지 않음으로써 검색 속도를 높일 수도 있지만, 16진수 문자열이 바이트 중간에서 일치하므로 잘못된 긍정이 발생할 수 있다는 점에 유의하세요. 이렇게 하면 각각 ..
대신 일치시킬 수 있습니다...
.
hexdump -v -e '/1 "%02X" ""' file.bin | \
grep -o "....$(printf "war" | hexdump -v -e '/1 "%02X" ""')" | \
xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash