여러 압축 파일을 연결하고 첫 번째 파일을 제외한 모든 헤더 줄을 건너뜁니다.

여러 압축 파일을 연결하고 첫 번째 파일을 제외한 모든 헤더 줄을 건너뜁니다.

gzip 압축 파일 세트가 있고 이를 단일 파일로 결합하고 싶습니다. 각각은 동일한 형식을 갖습니다. 첫 번째 파일의 헤더 정보만 유지하고 다음 파일에서는 건너뛰고 싶습니다.

간단한 예로, 다음 내용을 포함하는 4개의 동일한 파일이 있습니다.

$ gzcat file1.gz
# header
1
2

나는 끝내고 싶다

# header
1
2
1
2
1
2
1
2

현실적으로 파일 수가 다를 수 있으므로 프로그래밍 방식으로 이 작업을 수행하고 싶습니다. 지금까지 제가 가지고 있는 비프로그래밍 솔루션은 다음과 같습니다.

cat <(gzcat file1.gz) <(tail -q -n +2 <(gzcat file2.gz) <(gzcat file3.gz) <(gzcat file4.gz))

명령은 작동하지만 4개의 ​​파일을 처리하기 위해 "하드코드"되어 있으므로 이를 여러 파일에 일반화해야 합니다. 도움이된다면 bash쉘을 사용하고 있습니다. 제가 선호하는 것은 성능입니다(실제로 파일 길이는 수백만 줄에 달할 수 있습니다). 따라서 속도가 빠르다면 덜 우아한 솔루션도 괜찮습니다.

답변1

질문에 표시한 명령이 기본적으로 작동하는 경우(하드코딩된 파일 수에 대해)

first=1
for f in file*.gz
do
    if [ "$first" ]
    then
        gzcat "$f"
        first=
    else
        gzcat "$f"| tail -n +2
    fi
done > collection_single_file

당신을 위해 일해야합니다. 논리가 상당히 명확하기를 바랍니다. 모든 파일을 봅니다(파일 이름에 따라 와일드카드 변경). 목록의 첫 번째 파일인 경우 gzcat전체 파일(헤더 포함)을 가져옵니다. 그렇지 않으면 tail스트립 헤더를 사용하십시오. 한 파일이 처리되면 다른 파일은 더 이상 첫 번째 파일이 아닙니다.

이것은 전화할 것이다tail 질소한 번이 아니라 −1 번입니다(귀하의 답변과 같습니다). 그 외에는 내 대답이 당신의 대답과 같아야 합니다.

답변2

변종G-Man의 솔루션별도의 변수를 사용하지 않고 첫 번째 파일을 추적합니다.

set -- file*.gz

{
    gzcat "$1"; shift

    for file do
        gzcat "$file" | sed '1d'
    done
} >combined.txt

그러면 첫 번째 파일의 압축이 풀린 다음 나머지 파일을 반복하여 sed첫 번째 줄을 제거하는 짧은 스크립트에 각 파일을 전달합니다. 출력이 로 리디렉션됩니다 combined.txt.

set -- file*.gz명령은 위치 인수( $1, $2등, 집합적으로 배열이라고 함 $@)를 지정된 패턴과 일치하는 파일 이름으로 설정합니다. 압축을 푼 후 배열에서 shift제거 합니다. $1배열의 나머지 파일 이름을 반복합니다. 이는 다음과 같이 쓸 수도 있습니다.

for file in "$@"; do
    gzcat "$file" | sed '1d'
done

이를 { ... }통해 명령 출력을 한 번에 파일로 리디렉션할 수 있습니다.


더 짧게, "헤더 행"이 항상 문자로 시작하고 #(질문의 예에서와 같이) 데이터에 다른 행이 없다고 가정하면 다음과 같습니다.

gzcat file*.gz | awk 'NR > 1 && /^#/ { next } 1' >combined.txt

또는,

gzcat file*.gz | sed '2,${ /^#/d; }' >combined.txt

#압축되지 않은 데이터의 결합된 내용에서 두 번째 줄 이후에 나타나는 경우 두 방법 모두 처음부터 모든 줄을 건너뜁니다.

관련 정보