다른 명령의 출력을 사용하여 파일 필터링

다른 명령의 출력을 사용하여 파일 필터링

check_this파이프로 연결된 파일에 대해 YES 또는 NO를 인쇄하는 외부 명령이 있습니다.

cat myfile | check_this

YES
NO
YES
YES
...

이제 결과가 YES인 myfile의 모든 행을 가져오고 싶습니다. 이를 수행할 수 있는 방법이 있습니까? 현재는 임시 파일을 사용하고, 다른 파일에 저장한 후 붙여넣기 + grep을 사용하는데, 이는 번거롭고 견고하지 않습니다.

답변1

나는 다음을 사용할 것이다 awk:

<myfile check_this | awk '
  !check_processed {if ($1 == "YES") yes[FNR]; next}
  FNR in yes' - check_processed=1 myfile

awk해시 테이블의 단어로 시작하는 출력의 줄 번호를 기록한 check_this다음 해당 해시 테이블에 번호가 있는 줄을 인쇄합니다.YESyesmyfileyes

답변2

GNU이 버전 을 활용할 수 있습니다직류기본적으로 grep -f기능을 구현하는 유틸리티입니다.

dc -e "
$(< myfile check_this | sed -e 's/NO/0/;s/YES/1/' | tac)
[q]sq [p]sp [?z0=qr1=psxz0<?]s?
l?x
" < <(< myfile sed -e 's/.*/[&]/')
  • 첫 번째 단계에서는 check_this유틸리티의 출력을 로드하고 적절하게 부울린 후(YES => 1, NO => 0) 스택에 푸시합니다. 입력 파일에서 다음 줄을 읽고 스택에 푸시합니다. 두 번째 스택 요소가 1이면 인쇄합니다.

  • 그런 다음 스택의 상위 2개 요소를 지웁니다. EOF까지 반복합니다.

답변3

GNU awk는 gawk+paste라고도 알려져 있습니다.:

$ < myfile check_this \
   | paste myfile -      \
   | gawk '/YES$/ && NF--';
$ < myfile check_this \
    |  perl -lpe '
      @ARGV && do{
        /YES/ && $h{$.}++;
        eof && close(ARGV);
        next;
       };
        print if $h{$.};
  ' - myfile

GNU sed모드 extended regex가 켜져 있을 때:

$ < myfile check_this |
    sed -nE '
        1{:a;H;n;/^(YES|NO)$/ba;}
        G;/\n\nYES/P
        s/.*\n\n(YES|NO)/\n/;h
    ' - myfile

check_this 출력을 보류 상태로 저장하고 myfile의 각 줄을 확인하여 보류의 기본 값이 yes인지 확인합니다. 그런 다음 myfile 행을 인쇄하십시오. 패턴 공간에서 처음 두 요소를 잘라내고 패턴을 예약된 공간에 복원("복원" 아님)합니다.

답변4

@StéphaneChazelas의 완벽한 솔루션 awk의 변형은 덜 컴팩트하지만 외부 변수( check_processed그의 표기법에서)에 의존하지 않기 때문에 읽기가 더 쉬울 것입니다.

$ awk 'FNR == NR {if ($1 == "YES") yes[FNR];next} 
       FNR != NR && FNR in yes'   <(check_this <myfile) myfile

노트:@RakeshSharma는 next(첫 번째 줄)과 테스트 FNR != NR(두 번째 줄)를 동시에 사용하는 것은 중복된다고 언급했습니다. 이 모드의 사용자는 다음과 같이 출력을 변경하지 않고 그 중 하나를 제거할 수 있습니다.

$ awk 'FNR == NR {if ($1 == "YES") yes[FNR];next} 
       FNR in yes'   <(check_this <myfile) myfile

관련 정보