it-swarm-ko.tech

grep이 파일을 이진 파일로 간주하는 이유는 무엇입니까?

상자에 Windows 시스템에서 일부 데이터베이스 덤프가 있습니다. 텍스트 파일입니다. cygwin을 사용하여 grep하고 있습니다. 이들은 일반 텍스트 파일 인 것 같습니다. 메모장 및 워드 패드와 같은 텍스트 편집기로 파일을 열고 읽을 수있게 보입니다. 하지만 grep을 실행하면 binary file foo.txt matches.

파일에 ascii NUL 문자가 포함되어 있으며 데이터베이스 덤프의 아티팩트라고 생각합니다.

Grep이이 파일들을 바이너리로 간주하게 만드는 것은 무엇입니까? NUL 문자? 파일 시스템에 플래그가 있습니까? grep이 줄 일치를 표시하도록하려면 무엇을 변경해야합니까?

203
user394

파일의 어느 곳에 NUL 문자가 있으면, grep은이를 2 진 파일로 간주합니다.

cat file | tr -d '\000' | yourgrep와 같은 해결 방법으로 먼저 모든 null을 제거한 다음 파일을 검색 할 수 있습니다.

139
bbaja42

grep -a가 나를 위해 일했습니다.

$ grep --help
[...]
 -a, --text                equivalent to --binary-files=text
140
Plouff

strings 유틸리티를 사용하여 파일에서 텍스트 컨텐츠를 추출한 후 다음과 같이 grep를 통해 파이프 할 수 있습니다. strings file | grep pattern.

21
holgero

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 유니 코드 포인트의 첫 바이트가 될 수 없기 때문에 : TF-8-Description | en.wikipedia.org

또한 Stéphane Chazelas가 언급 한 것처럼 grep가 파일을 이진 파일로 간주하는 이유는 무엇입니까? | Unix & Linux Stack Exchange , 이러한 검사는 길이 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

encoding_error_output에 대한 빠른 grepping은이를 수정할 수있는 유일한 코드 경로가 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가됩니다.

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
6
zzapper

/etc/magic 또는 /usr/share/misc/magic 파일에는 file 명령이 파일 형식을 결정하는 데 사용하는 시퀀스 목록이 있습니다.

이진은 대체 솔루션 일 수 있습니다. 때때로 이상한 인코딩을 가진 파일도 이진으로 간주됩니다.

Linux의 grep에는 --binary-files 또는 -U / --binary와 같은 이진 파일을 처리 할 수있는 옵션이 있습니다.

5
klapaucius

실제로 "grep가 파일을 이진 파일로 간주하게 만드는 이유"라는 질문에 대답하면 iconv를 사용할 수 있습니다.

$ iconv < myfile.Java
iconv: (stdin):267:70: cannot convert

필자의 경우 텍스트 편집기에서 올바르게 표시되는 스페인어 문자가 있었지만 grep은 해당 문자를 이진으로 간주했습니다. iconv 출력은 해당 문자의 줄과 열 번호를 가리 켰습니다.

NUL 문자의 경우 iconv는 해당 문자를 정상으로 간주하고 이러한 종류의 출력을 인쇄하지 않으므로이 방법은 적합하지 않습니다.

2
golimar

내 학생 중 한 명이이 문제를 겪었습니다. grepCygwin에 버그가 있습니다. 파일에 ASCII가 아닌 문자가있는 경우 grepegrep는 이진 파일로 표시됩니다.

2
Joan Pontius

나는 같은 문제가 있었다. 추가 된 문자를 보려면 vi -b [filename]를 사용했습니다. 제어 문자 ^@^M를 찾았습니다. 그런 다음 vi에서 :1,$s/^@//g를 입력하여 ^@ 문자를 제거하십시오. ^M에 대해이 명령을 반복하십시오.

경고 : "파란색"제어 문자를 얻으려면 Ctrl+v 그때 Ctrl+M 또는 Ctrl+@. 그런 다음 vi를 저장하고 종료하십시오.

1
Not Sure