재귀 grep은 일부 파일의 일치 항목을 나열하지 않습니다.

Aug 20 2020

특정 패턴을 포함하는 스크립트를 찾기 위해 GNU grep 3.4를 사용하고 있습니다. 이를 위해 이렇게 grep재귀 적으로 호출합니다.

grep -rin . -e "pattern" 

패턴은 정규식이 아닌 단어 일뿐입니다. 이상한 점은 출력이 문자열을 확실히 포함하는 일부 파일의 발생을 나열하지 않는다는 것입니다.

이 파일을 열고 vim사용하여 검색 을 시도 /pattern했으며 패턴을 찾습니다. 인코딩은 표시되는 vim[dos:utf-8:]. 줄을 복사하여 새 파일에 쓰면 위의 grep명령이 올바르게 나열합니다.

grep원본 파일이 나열 되지 않는 이유는 무엇 입니까?

답변

1 RedGrittyBrick Aug 20 2020 at 20:08

Grep (또는 적어도 이전 버전)는 UTF8을 이해하지 못합니다. 따라서 구성된 문자, 하이픈 포인트 또는 기타 보이지 않는 데이터는 grep을 방해 할 수 있습니다.

Grep은 다음 값의 영향도받습니다. $LC_ALL, $LC_CTYPE 및 $ LANG.

vim을 사용하여 grep이 찾지 못한 단어 주위에 몇 줄을 저장 한 다음 그 작은 예제 파일의 hexdump를 만드십시오. grep이 실패한 이유를 알게 될 것입니다.

당신은 또한 (정력 명령을 사용할 수 있습니다 ga, g8문자를 검사 등)하지만 헥스 덤프 명확하게 할 수있다

1 buddemat Aug 20 2020 at 22:28

나는 문제를 발견했습니다 (다른 답변의 도움으로). 'grep'파일은 실제로 utf-8인코딩 되지 않았지만 utf-16be. 나는 hexdump (@RedGrittyBrick에 대한 크레딧)를 사용하여 이것을 배웠습니다.

hd file_for_which_grep_works_as_expected.txt

양보

00000000  20 20 20 20 50 61 74 74  65 72 6e 0a              |    Pattern.|
0000000c

이므로

hd file_for_which_grep_fails.txt

반환

00000000  fe ff 00 50 00 61 00 74  00 74 00 65 00 72 00 6e  |...P.a.t.t.e.r.n|
00000010  00 0a                                             |..|
00000012

따라서 인코딩을 다시 확인하십시오.

file -i file_for_which_grep_fails.txt

으로 식별했습니다 text/plain; charset=utf-16be.

utf-8표시된 파일vim 이 실제로 파일 인코딩이 아닌 버퍼 인코딩 이라는 것을 인식하지 못했습니다 . 실행 에 도 올바르게 표시 (여기:set fileencodingvimfileencoding=utf-16https://superuser.com/a/28783/1210682).

따라서 문제는 인코딩 된 파일에서 grep작동하지 않는다는 것입니다 utf-16. 이것은 이미 여기에 설명되어 있습니다.https://superuser.com/a/231471/1210682. 그러나, 변환의 치료 utf-16에 파일을 utf-8하기 전에 grep내가 재귀를 사용할 때 작동하지 않습니다 나는 파일이있을 수있는 사전에 알고하지 않는 한 utf-8어느 utf-16와 많은 파일을 통해 오전 검색.

다른 솔루션이 있습니다. 그 중 두 가지를 여기서 간단히 설명하겠습니다.

  1. 빠른 - 및 - 더러운 나를 위해 일한 솔루션은 일치합니다 하나를 포함하는 검색 패턴을 확장했다 utf-16버전을 두 패턴 중 하나를 검색을 :

    grep -riPa . -e "pattern|p.a.t.t.e.r.n."
    

    물론 이것은 가능한 패턴 측면에서 매우 제한적입니다.

  2. greplike ugrep또는 ripgrepthat (무엇보다도)에 대한 대안이 utf-16파일 을 처리 할 수 ​​있습니다 . ripgrep18.04의 표준 Ubuntu 패키지 리포지토리에서 사용할 수있는 것을 사용 하게되었습니다.

    rg -i "pattern"  
    

여기에 대안에 대한 훌륭한 토론이 있습니다. https://stackoverflow.com/questions/3752913/grepping-binary-files-and-utf16, 그들 중에는 검색 패턴을로 변환하고이를로 utf-16공급 하려는 흥미로운 접근 방식 이 grep있습니다. 그러나 나는 그것을 작동시킬 수 없었다.