grep이 파일을 이진 파일로 간주하는 이유는 무엇입니까? 워드 패드와 같은 텍스트 편집기로 파일을

상자에 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'
    

    때문에 \x80UTF-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이 파일 유형을 결정하는 데 사용 하는 시퀀스 목록이 있습니다.

참고 바이너리 그냥 대체 솔루션이 될 수 있습니다. 때때로 이상한 인코딩을 가진 파일도 이진으로 간주됩니다.

grepLinux에는 --binary-files또는 같은 이진 파일을 처리하는 몇 가지 옵션이 있습니다.-U / --binary


답변

내 학생 중 한 명이이 문제를 겪었습니다. 에 버그가 grep있습니다 Cygwin. 파일이 ASCII가 아닌 문자를 가지고있는 경우 grepegrep진로를 참조하십시오.