상자에 Windows 시스템에서 일부 데이터베이스 덤프가 있습니다. 텍스트 파일입니다. cygwin을 사용하여 grep하고 있습니다. 이들은 일반 텍스트 파일 인 것 같습니다. 메모장 및 워드 패드와 같은 텍스트 편집기로 파일을 열고 읽을 수있게 보입니다. 그러나 grep을 실행하면라고 말합니다 binary file foo.txt matches
.
파일에 일부 ASCII NUL
문자가 포함되어 있으며 데이터베이스 덤프의 아티팩트라고 생각합니다.
grep이이 파일들을 바이너리로 간주하게 만드는 것은 무엇입니까? NUL
문자? 파일 시스템에 플래그가 있습니까? grep이 줄 일치를 표시하도록하려면 무엇을 변경해야합니까?
답변
NUL
파일 어딘가에 문자 가 있으면 , grep은이를 2 진 파일로 간주합니다.
이러한 방법으로 cat file | tr -d '\000' | yourgrep
모든 null을 먼저 제거한 다음 파일을 검색 할 수 있습니다.
답변
grep -a
나를 위해 일했다 :
$ grep --help
[...]
-a, --text equivalent to --binary-files=text
답변
당신이 사용할 수있는 strings
텍스트의 모든 파일의 내용 다음 파이프를 통해 추출 유틸리티를 grep
이 등을 : strings file | grep pattern
.
답변
GNU grep 2.24 RTFS
결론 : 2와 2의 경우 만 :
-
NUL
예를 들어printf 'a\0' | grep 'a'
-
C99에 따른 인코딩 오류
mbrlen()
, 예 :export LC_CTYPE='en_US.UTF-8' printf 'a\x80' | grep 'a'
때문에
\x80
UTF-8 유니 포인트의 첫 번째 바이트가 될 수 없습니다 : UTF-8 – 설명 | en.wikipedia.org
또한 Stéphane Chazelas가 언급했듯이 grep이 파일을 이진 파일로 간주하게 만드는 이유는 무엇입니까? | 유닉스 및 리눅스 스택 교환에서 , 이러한 검사는 TODO 길이의 첫 번째 버퍼 읽기까지만 수행됩니다.
첫 번째 버퍼 읽기까지만
따라서 매우 큰 파일 중간에 NUL 또는 인코딩 오류가 발생하면 어쨌든 잘릴 수 있습니다.
이것이 성능상의 이유라고 생각합니다.
예 : 줄을 인쇄합니다 :
printf '%10000000s\n\x80a' | grep 'a'
그러나 이것은하지 않습니다 :
printf '%10s\n\x80a' | grep 'a'
실제 버퍼 크기는 파일을 읽는 방법에 따라 다릅니다. 예 : 비교 :
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
을 사용하면 sleep
프로세스가 잠자기 때문에 첫 번째 행이 1 바이트 길이 인 경우에도 grep에 전달되고 두 번째 읽기는 파일이 이진인지 확인하지 않습니다.
RTFS
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
stderr 오류 메시지가 인코딩 된 위치를 찾으십시오.
git grep 'Binary file'
우리를 이끌어줍니다 /src/grep.c
:
if (!out_quiet && (encoding_error_output
|| (0 <= nlines_first_null && nlines_first_null < nlines)))
{
printf (_("Binary file %s matches\n"), filename);
이러한 변수의 이름이 잘 정해지면 기본적으로 결론에 도달했습니다.
encoding_error_output
빠른 grepping for encoding_error_output
는 그것을 수정할 수있는 유일한 코드 경로가 통과한다는 것을 보여줍니다 buf_has_encoding_errors
.
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
그럼 그냥 man mbrlen
.
nlines_first_null 및 nlines
다음과 같이 초기화 됨 :
intmax_t nlines_first_null = -1;
nlines = 0;
따라서 null이 발견 0 <= nlines_first_null
되면 true가됩니다.
TODO는 nlines_first_null < nlines
언제 거짓 일 수 있습니까? 게으르다
POSIX
바이너리 옵션 grep을 정의하지 않음 -패턴을 찾기 위해 파일 검색 | pubs.opengroup.org 및 GNU grep 은이를 문서화하지 않으므로 RTFS가 유일한 방법입니다.
답변
내 텍스트 파일 중 하나가 grep에 의해 갑자기 바이너리로 표시되었습니다.
$ file foo.txt
foo.txt: ISO-8859 text
해결책은 다음을 사용하여 변환하는 것입니다 iconv
.
iconv -t UTF-8 -f ISO-8859-1 foo.txt > foo_new.txt
답변
파일 /etc/magic
또는 /usr/share/misc/magic
명령 file
이 파일 유형을 결정하는 데 사용 하는 시퀀스 목록이 있습니다.
참고 바이너리 그냥 대체 솔루션이 될 수 있습니다. 때때로 이상한 인코딩을 가진 파일도 이진으로 간주됩니다.
grep
Linux에는 --binary-files
또는 같은 이진 파일을 처리하는 몇 가지 옵션이 있습니다.-U / --binary
답변
내 학생 중 한 명이이 문제를 겪었습니다. 에 버그가 grep
있습니다 Cygwin
. 파일이 ASCII가 아닌 문자를 가지고있는 경우 grep
와 egrep
진로를 참조하십시오.