grep용 리디렉션 및 파이프

grep용 리디렉션 및 파이프

STDOUT으로 출력하는 체크섬 프로세스를 실행할 스크립트를 작성 중입니다. 그런 다음 OK 또는 FAILED와 일치하는 줄을 찾아 해당 일치 항목에 대해 다른 작업(예: 터미널 및 로그로 출력)을 수행하려고 합니다. YouTube 동영상을 많이 보고 리디렉션에 대해 많이 읽었지만 리디렉션이 정확히 어떻게 작동하는지 이해하지 못하는 것 같습니다. 내가 하고 싶은 것은 일치하지 않는 텍스트를 먹지 않고 STDOUT을 여러 grep에 연결하는 것입니다.

다음은 한 줄에 하나의 동물 이름(DOG, CAT, PONY, RHINO, DEER, FOX)이 있는 텍스트 파일인 md5sum 대신 cat을 사용하여 시도한 개념입니다.

{ cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3> results.txt

이것이 내가 기대했던 것입니다. 여기서 내가 이해하는 것은 파일을 cating한 다음 STDOUT(fd1)에 기록된 내용을 가리키는 fd3을 여는 것입니다. grep은 fd1의 모든 것을 먹기 때문에 명시적으로 cat의 STDOUT을 fd3에 보낸 다음 STDOUT을 grep으로 파이프합니다. Grep은 DOG와 일치하는 행을 인쇄한 다음 cat에서 fd3에 작성된 모든 텍스트가 results.txt 파일로 푸시됩니다.

이제 추가 텍스트를 찾기 위해 또 다른 grep을 연결하려면 fd3 데이터를 STDOUT으로 지정하고 명시적으로 fd3으로 반환한 다음 STDOUT을 새 grep으로 파이프해야 합니다.

{ { cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3>&1 | tee /dev/fd/3 | grep PONY; } 3> results.txt

여기서 첫 번째 문제는 첫 번째 grep의 STDOUT이 터미널에 인쇄되는 대신 두 번째로 fd3에 푸시된다는 것입니다. 이제 results.txt가 중복되어 첫 번째 grep에서 화면에 아무것도 인쇄되지 않습니다. 이것이 리디렉션에 대한 나의 이해가 무너지는 곳입니다. 무슨 일이 일어나고 있는지 이해하지만 간단한 해결책을 찾을 수 없습니다.

STDOUT을 grep하고 결과를 화면에 인쇄하고 각 GREP에 전달하는 원본 텍스트를 수정하지 않고 원본 텍스트를 다른 grep, 세 번째, 네 번째 등에 전달하고 싶습니다. 이후의 각 grep은 그렇지 않습니다. 화면에 인쇄되어야 하는 이전 '일치'를 먹습니다.

변수를 저장하고 여러 줄에 걸쳐 grep을 호출하면 이 작업을 수행할 수 있지만 첫 번째 명령 전체가 완료될 때까지 기다려야 합니다. 제가 개발 중인 애플리케이션의 경우 전체 프로세스가 완료될 때까지 한 시간 동안 빈 화면만 표시되는 것이 아니라 체크섬 중에 실시간 결과를 확인하고 싶습니다. 내가 뭘 잘못하고 있는지에 대한 명확한 설명은 매우 도움이 될 것입니다. 감사합니다!

편집하다

나는 cat의 정확한 사용법이 의미가 없다는 것을 알고 있으며 단지 개념을 보여주기 위해 그것을 사용하고 있습니다. 이 개념을 적용할 스크립트에서 첫 번째 명령은 실제로 다음과 같습니다.

md5sum -c checksum.md5

체크섬 파일을 읽고, 소스를 다시 해시하고, 통과/실패 행을 STDOUT으로 출력합니다. 그런 다음 이 스트림을 grep하고 결과를 별도의 로그 및/또는 터미널 출력으로 보내고 싶었지만 cat이 문제를 설명하는 더 쉬운 방법인 것 같습니다. 이는 모든 명령을 필터링하고 다음과 같은 스트림을 grep하는 데 적용할 수 있기 때문입니다. 찾기, md5, ls 등

답변1

프로세스 대체를 통해 원하는 작업을 더 잘 수행할 수 있습니다.

  1. 원래 명령에 최대한 가깝게:

    cat test.txt | tee >(grep DOG) >(grep PONY) >results.txt
    
  2. 쓸모없는 cat 사용을 제거하십시오.

    <test.txt tee >(grep DOG) >(grep PONY) >results.txt
    

    또는:

    tee >(grep DOG) >(grep PONY) <test.txt >results.txt
    

답변2

isaac의 솔루션이 더 좋지만 접근 방식은 다음과 같습니다.

{ <input tee results.txt /dev/fd/3 | grep DOG >&2; } 3>&1 |
    { tee /dev/fd/3 | grep PONY >&2; } 3>/dev/null

아니면 셋

{ <input tee results.txt /dev/fd/3 | grep DOG >&2; } 3>&1 |
    { tee /dev/fd/3 | grep PONY >&2; } 3>&1 |
    { tee /dev/fd/3 | grep CAT >&2; } 3>/dev/null

관련 정보