화면에 쓰지 않고 결과를 여러 명령으로 파이프

화면에 쓰지 않고 결과를 여러 명령으로 파이프

압축을 풀고 싶은 아주 큰 zip 파일(~10GB)이 있고 그 결과는 두 개의 명령으로 전달되어야 합니다. 두 후속 명령의 결과는 파일에 추가되어야 하며

현재 나는 달리고있다

unzip -p bigFile.zip | head -n 1 >> output.txt
unzip -p bigFile.zip | grep -v 'skipLine' >> output.txt

이것은 약 백만 개의 행을 제공합니다. 이제 1행으로 하고 싶습니다. 나는 사용하기 tee시작했다

unzip -p bigFile.zip | tee >(head -n 1 >> output.txt) >(grep -v 'skipLine' 
>> output.txt)

그러나 output.txt파일에는 51줄만 포함되어 있으며 그 중 마지막 줄은 완전하지도 않습니다. 또한 후자의 명령은 내가 원하지 않는 결과를 터미널에 인쇄합니다.

나도 시도했다

unzip -p bigFile.zip | tee >(head -n 1 >> output.txt) | grep -v 'skipLine' 
>> output.txt

그러나 불행히도 이것도 작동하지 않습니다.

어떤 도움이라도 대단히 감사하겠습니다! 를 사용할 필요가 없습니다 . 위젯의 출력을 and 명령 에 tee전달할 수 있는 한 다른 명령은 잘 작동합니다 .unzipheadgrep

편집하다:head및 명령의 출력을 "결합"한 다음 에 전달할 수 있다면 grep훨씬 더 좋을 것입니다 zip. 가능합니까?

답변1

첫 번째 줄을 가져와 인쇄하고 grep이 나머지를 사용할 수 있도록 하는 쉘 스크립트의 압축을 풀고 파이프할 수 있습니다.

unzip -p bigFile.zip | {
    IFS= read -r header       # consume the first line, verbatim
    printf "%s\n" "$header"
    grep -v 'skipLine' 
} >> output.txt

블록에서 인쇄된 모든 내용은 출력 파일에 추가됩니다.

답변2

두 개의 개별 명령을 파이프하는 방법은 생각할 수 없지만 다음을 사용할 수 있습니다 awk.

unzip -p file.zip | awk 'NR==1 || !/skipLine/' > output

NR==1awk 명령은 현재 행이 첫 번째 행( )이거나 일치하지 않는 경우 skipline( )를 인쇄합니다.!/skipLine

내가 생각할 수 있는 가장 좋은 조합 grep은 다음과 같습니다 head.

unzip -p file.zip | tee >(head -n1 > output) | tail -n+2 | grep -v skipLine >> output

아이디어는 첫 번째 줄을 먼저 캡처한 다음 head -n1다음을 사용하여 tail -n+2첫 번째 줄을 제외한 모든 것을 인쇄하는 것입니다.grepawk

답변3

미묘한 점이 빠졌을 수도 있지만 첫 번째 줄을 유지하고 첫 번째 줄 이후에 고유한 텍스트가 포함되지 않은 내용을 유지하려는 것 같습니다 skipLine. sed이 일을 잘 처리할 것 같습니다 .

#!/bin/bash
sed -n '1 {p;d}         #for line 1, print and discard
        /skipLine/d     #delete any line with skipLine
        p               #print remainder
' << End_of_SampleData
head
prefix skipLine
keepLine
skipLine suffix
keepLine
End_of_SampleData

산출:

head
keepLine
keepLine

unzip -p bigFile.zip | sed ...이 테스트 사례가 요구 사항을 충족하는 경우 데이터를 이 스크립트로 파이프할 수 있습니다. 실행할 프로세스 는 단 unzip하나 뿐이므로 속도가 빨라야 합니다 .sed

답변4

명령에 두 가지 문제가 발생합니다 tee.

tee >(head -n 1 >>output.txt) >(grep -v 'skipLine' >>output.txt)

가장 간단한 것은 출력을 삭제하려는 경우입니다. 이렇게 하려면 간단히 표준 출력을 /dev/null로 보내면 됩니다.

tee >(head -n 1 >>output.txt) >(grep -v 'skipLine' >>output.txt) >/dev/null

그러나 이것은 낭비적인 것처럼 보입니다. tee두 번째 명령을 표준 출력에 연결하는 것이 더 효율적입니다.

tee >(head -n 1 >>output.txt) | grep -v 'skipLine' >>output.txt

두 번째는 head필요한 입력을 읽은 후 닫는 것입니다. 간단한 수정은 입력을 삭제하는 절차를 사용하는 것입니다.

tee >(head -n 1 >>output.txt; dd of=/dev/null) | grep -v skipLine >>output.txt

이 파이프가 이전 콘텐츠를 대체하도록 하려면 두 개의 열기를 output.txt하나로 바꿀 수 있습니다.

exec 3>output.txt
tee >(head -n 1 >&3; dd of=/dev/null) | grep -v skipLine >&3

두 개의 독립 파이프가 있는 초기 버전과 달리 이러한 모든 버전에서는 헤더 행이 출력 파일의 시작 부분에 있다는 보장이 없습니다. 이것이 요구 사항인 경우 교체에 대한 다른 답변 중 하나를 확인하십시오(또는 sleep이전 시퀀스를 사용한 도박 grep).

하지만 이 답변이 도움이 되었으면 좋겠습니다이해하다왜 숟가락으로 떠먹여주는 대안 대신 자신이 하는 일의 결과를 볼 수 있을까요?

관련 정보