'grep -q'가 전체 입력 파일을 사용하는 이유는 무엇입니까?


23

다음 입력 파일을 고려하십시오.

1
2
3
4

달리는

{ grep -q 2; cat; } < infile

아무것도 인쇄하지 않습니다. 나는 그것을 인쇄 할 것으로 예상된다

3
4

변경하면 예상 출력을 얻을 수 있습니다.

{ sed -n 2q; cat; } < infile

첫 번째 명령이 예상 출력을 인쇄하지 않는 이유는 무엇입니까?
검색 가능한 입력 파일이며 OPTIONS표준에 따라 다릅니다 .

-q
      Quiet. Nothing shall be written to the standard output, regardless of 
      matching lines. Exit with zero status if an input line is selected.

그리고 APPLICATION USAGE ( 강하게 강조) 에서 아래로 :

-q옵션을 사용하면 파일 그룹에 패턴 (또는 문자열)이 있는지 여부를 쉽게 확인할 수 있습니다. 여러 파일을 검색 할 때 성능이 향상됩니다 ( 첫 번째 일치 항목을 찾 자마자 종료 될 수 있기 때문에 ) [...]

이제 동일한 표준에 따라 ( 소개 , 입력 파일 아래에 있음 )

표준 유틸리티가 탐색 가능한 입력 파일을 읽고 파일 끝에 도달하기 전에 오류없이 종료되는 경우 , 유틸리티는 열린 파일 설명의 파일 오프셋이 유틸리티가 처리 한 마지막 바이트 바로 뒤에 올바르게 위치하도록해야합니다 [. ..]

tail -n +2 file
(sed -n 1q; cat) < file
...

두 번째 명령은 파일을 찾을 수있는 경우에만 첫 번째 명령과 같습니다.


grep -q전체 파일을 소비합니까?


이것은 gnu grep중요하다면 ( Kusalananda 가 OpenBSD에서 동일한 일이 발생했음을 확인 했지만 )


OpenBSD grep궁금한 점이 있으면 FreeGrep 이라는 포크입니다 .
Kusalananda

답변:


37

grep 일찍 멈추지 만 입력을 버퍼링하므로 테스트가 너무 짧습니다 (그리고 테스트를 찾을 수 없기 때문에 테스트가 불완전하다는 것을 알았습니다).

seq 1 10000 | (grep -q 2; cat)

내 시스템에서 6776에 시작합니다. GNU grep에서 기본적으로 사용되는 32KiB 버퍼 와 일치 합니다 .

seq 1 6775 | wc

출력

   6775    6775   32768

POSIX는 성능 향상만을 언급합니다.

여러 파일을 검색 할 때

단일 파일을 부분적으로 읽음으로써 성능 향상에 대한 기대치를 설정하지는 않습니다.


2

이것은 분명히 grep속도를 높이는 버퍼링 때문입니다. 요청한 문자 수만큼만 읽도록 특별히 설계된 도구가 있습니다. 그들 중 하나는 expect:

{ expect -c "log_user 0; expect 2"; cat; } < infile

나는 이것을 시도 할 시스템이 없지만 expect예상되는 문자열 ( 2)을 만날 때까지 모든 것을 먹은 다음 종료하고 나머지 입력은 그대로 둡니다 cat.


1

sed와 grep을 혼동하고 있습니다.

sed 명령의 -2q경우 두 번째 줄에서 -n옵션이 조용히 작동한다고 말하면 현재 반복을 종료한다고 말하고 두 번째 줄 이후에 모든 줄을 얻습니다.

grep 명령은 기본적으로 모든 일치하는 행을 출력하기 위해 실행되지만 -q옵션은 stdout에 아무것도 출력하지 않습니다. 따라서 입력에 "2"가 포함되어 있으면 종료 값이 SUCCESS이고 그렇지 않으면 FAILURE입니다. 그것들은 운영 체제와 쉘에 따라 다릅니다. 따라서 일반적으로 grep 프로세스의 종료 값을 검사하여 행이 일치하는지 알 수 있습니다. 이것은 입력에 테스트 값이 포함되어 있는지 알고 싶은 파이프 라인에서 유용합니다. 예 :

if grep -q 'crash' <somelog.log ; then report_crash_via_email ; fi

이 경우 일치하는 줄을 모두 보지 않아도되며, 적어도 한 줄만 있으면됩니다. report_crash_via_email프로세스 / 기능은 전원을 껐다 갈 수 있으며 파일을 다시는-열거 나하지.

"2"문자를 찾은 후 grep 프로세스를 중지하려면 기본적으로는 아니고 모든 행을 검사하여 일치하는지 확인합니다.이를 수행하도록 지시해야합니다. 해당 명령 줄 스위치는 -m <value>입니다. 귀하의 경우에는 grep -q -m1 2.


6
귀하의 답변은 일반적인 사용에 유용한 정보 grep이지만이 질문은 더 미묘하고 난해한 것에 대해 묻고 있습니다. 쿼리되는 실제 동작을 이해하기에 너무 빨리 질문을 읽은 것 같습니다. 또한 GNU grep -q POSIX 사양에서 인용 한대로 다음 과 같이 사용될 때 검색을 중지 합니다. GNU grep의 맨 페이지에는 "일치하는 것이 있으면 상태가 0이면 즉시 종료 합니다 "라고 나와 있습니다. FWIW, 귀하의 질문을 수정하여 향후 게시물의 형식을 지정하는 방법을 보여주었습니다. Welcom에서 스택 교환 .
Anthony G-Monica에 대한 정의

@ user212377의 대답은 정확합니다.이 경우 grep파일에 '2'가 있는지 묻는 메시지가 표시됩니다. 그것은 처럼 행동 하지 않습니다sed해당 시점까지 레코드 하고 소비 추가 처리를 위해 나머지를 남겨 둡니다. '2'가 있거나없는 것을 알 때까지 읽고 파일을 닫고 결과를 반환합니다.
Keith Davies

grep실제로 검색 문자열이 파일에없는 경우 (전체 파일을 검사해야만 가능) 버퍼링 고려 사항을 무시하고 '전체 파일을 소비합니다'. 그보다 적은 것은 파일 읽기 가 중지 되고 파일이 닫히고 SUCCESS가 반환 된 것입니다.
Keith Davies
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.