unix - 巨大な .gz ファイルを行ごとに分割する

unix - 巨大な .gz ファイルを行ごとに分割する

きっと誰かが以下のようなニーズを抱えていると思いますが、巨大な .gz ファイルを行ごとに分割する簡単な方法は何でしょうか? 基になるテキスト ファイルには 1 億 2000 万行あります。ファイル全体を一度に gunzip するのに十分なディスク領域がないので、ファイル (.gz または内部の .txt) を 3 つの 4000 万行のファイルに分割できる bash/perl スクリプトまたはツールを知っている人がいないかと思っています。つまり、次のように呼び出します。

    bash splitter.sh hugefile.txt.gz 4000000 1
 would get lines 1 to 40 mn    
    bash splitter.sh hugefile.txt.gz 4000000 2
would get lines 40mn to 80 mn
    bash splitter.sh hugefile.txt.gz 4000000 3
would get lines 80mn to 120 mn

これらを連続して実行することが解決策になるでしょうか、それとも gunzip -c ではファイル全体を解凍するのに十分なスペースが必要になるでしょうか (つまり、元の問題): gunzip -c hugefile.txt.gz | head 4000000

注: 追加のディスクは入手できません。

ありがとう!

答え1

これを最も効果的に行う方法は、何を望んでいるかによって異なります。

  • 大きなファイルの一部を抽出しますか?
  • それとも、すべてのパーツを一度に作成しますか?

もしあなたがファイルの一部、あなたのアイデアはgunzip正しいheadです。次のものを使用できます。

gunzip -c hugefile.txt.gz | head -n 4000000

これにより、最初の 4000000 行が標準出力に出力されます。実際にデータに対して何かを行うには、別のパイプを追加する必要があるでしょう。

head他の部分を取得するには、次のようにとの組み合わせを使用しますtail

gunzip -c hugefile.txt.gz | head -n 8000000 |tail -n 4000000

2番目のブロックを取得します。

これらを連続して実行するのが解決策でしょうか、それともgunzip -cではファイル全体を解凍するのに十分なスペースが必要でしょうか

いいえ、gunzip -cディスク スペースは必要ありません。すべてをメモリ内で実行し、それを stdout にストリーム出力します。


作成したい場合はすべての部品を一度に、入力ファイルが一度だけ読み込まれるため、すべてを 1 つのコマンドで作成した方が効率的です。 1 つの良い解決策は を使用することですsplit。詳細については、jim mcnamara の回答を参照してください。

答え2

パイプを分割するには、gunzip -c または zcat を使用してファイルを開きます。

gunzip -c bigfile.gz | split -l 400000

分割コマンドに出力仕様を追加します。

答え3

(巻き戻し不可能な) ストリームで作業している場合は、行 N 以降から始まる行を取得するために、tail の '+N' 形式を使用する必要があります。

zcat hugefile.txt.gz | head -n 40000000
zcat hugefile.txt.gz | tail -n +40000001 | head -n 40000000
zcat hugefile.txt.gz | tail -n +80000001 | head -n 40000000

答え4

.gz ファイルを .gz ファイルに直接分割します。

zcat bigfile.gz | split -l 400000 --filter='gzip > $FILE.gz'

OP が望んでいたのはこれだと思います。スペースがあまりないからです。

関連情報