複数の圧縮ファイルをリンクし、最初のファイルを除くすべてのヘッダー行をスキップします。

複数の圧縮ファイルをリンクし、最初のファイルを除くすべてのヘッダー行をスキップします。

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回ではなく-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

#圧縮されていないデータの組み合わせで2行目以降に表示される場合、両方の方法が最初からすべての行をスキップします。

関連情報