tail 다음에 두 번 grep을 수행할 수 없는 이유는 무엇입니까?

tail 다음에 두 번 grep을 수행할 수 없는 이유는 무엇입니까?

이 명령을 성공적으로 실행할 수 있습니다.

tail -f my_file.txt | grep foo

문자열이 있는 행만 표시 foo하고 항상 표시합니다.

하지만 이 명령을 실행하면:

tail -f my_file.txt | grep foo | grep bar

foo일부에 및 가 모두 포함된 경우에도 행은 표시되지 않습니다 bar.

한 번의 호출로 여러 모드를 사용하는 솔루션 이 있다는 것을 알고 있지만 grep이 회선이 왜 실패하는지 궁금합니다.

답변1

이는 C 런타임 라이브러리의 기본 동작이 stdout이 터미널에 연결되어 있지 않은 한 전체 데이터 블록(일반적으로 몇 킬로바이트)이 기록될 때까지 stdout에 대한 쓰기를 버퍼링하는 것이기 때문입니다.

중간 grep이 전체 블록을 인쇄하면 출력을 얻지만 다음 블록이 채워질 때까지 다시 기다려야 합니다. 이는 처리량 최적화이며 left 명령이 특정 작업만 수행하고 일부 작업을 기다리는 대신 종료할 때 더 잘 작동합니다.

GNU grep에는 --line-buffered해당 버퍼링을 끌 수 있는 옵션이 있으므로 이것이 더 잘 작동할 것입니다:

tail -f my_file.txt | grep --line-buffered foo | grep bar

마지막 항목은 grep터미널에 인쇄되므로 기본적으로 라인 버퍼링되며 옵션이 필요하지 않습니다.

바라보다 파이프라인에서 버퍼링 끄기버퍼링 문제에 대한 일반적인 솔루션.


두 개의 grep을 사용하는 이 특별한 경우에는 Stéphane Chazelas가 설명에서 언급한 것처럼 단일 AWK를 대신 사용할 수 있습니다.

tail -f my_file.txt | awk '/foo/ && /bar/'

(그런데, 라인을 캡처하지만 awk '/foo/ && !/bar/'사용 하지 않고 비슷한 작업을 수행할 수도 있습니다 .)foobar

grep에서 동일한 작업을 수행하는 것은 다음 grep -e foo -e bar을 포함하는 모든 행을 일치시키기 때문에 더 어려울 것입니다.누구나 foo 또는 bar. 당신은 다음과 같은 것이 필요합니다

... | grep -E -e 'foo.*bar|bar.*foo'

대신에.

답변2

부울 관점에서 보면 기대하는 것 같습니다.부자또는술집grep을 사용하지만 수행하는 방식에서 예상해야합니다.부자그리고술집-- grep될 유일한 라인술집합격한 사람들부자먼저 그렙입니다.

foo/bar를 표준 출력에 표시하려면 다음을 사용해야 합니다.

tail -f my_file.txt | grep "foo|bar"

"pretty|much|like|this"만큼 많은 키워드를 추가할 수 있습니다. 단, 따옴표를 잊지 마세요. (또는 사용\|따옴표가 없는\| 여러 용어)

두 번째 요점: 그렇기 때문에꼬리 -f(아래) your_file.txt에 특정 시간에 두 키워드가 모두 추가된 행이 없을 수도 있으며 일반적으로 예상한 콘텐츠가 있는 것으로 알려진 해당 파일의 공유를 잘라내는 것이 가장 좋습니다.

tail -n 500 my_file.txt > my_sample.txt

거기에서 알려진 텍스트를 사용하여 원하는 grep 작업을 시도할 수 있습니다. (마지막 500개 행이면 충분할 것 같습니다. 필요에 따라 조정하세요.)

관련 정보