unix - divide um enorme arquivo .gz por linha

unix - divide um enorme arquivo .gz por linha

Tenho certeza de que alguém teve a necessidade abaixo. Qual é uma maneira rápida de dividir um arquivo .gz enorme por linha? O arquivo de texto subjacente possui 120 milhões de linhas. Não tenho espaço em disco suficiente para compactar o arquivo inteiro de uma vez, então gostaria de saber se alguém conhece um script ou ferramenta bash/perl que possa dividir o arquivo (o .gz ou o .txt interno) em 3 arquivos de linha de 40 minutos . ou seja, chamando-o como:

    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

Talvez uma série dessas seja uma solução ou o gunzip -c exigiria espaço suficiente para que o arquivo inteiro fosse descompactado (ou seja, o problema original): gunzip -c enormefile.txt.gz | cabeça 4000000

Nota: não consigo disco extra.

Obrigado!

Responder1

A melhor forma de fazer isso depende do que você deseja:

  • Você deseja extrair uma única parte do arquivo grande?
  • Ou você deseja criar todas as peças de uma só vez?

Se você quiser umúnica parte do arquivo, sua ideia de usar gunzipe headestá certa. Você pode usar:

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

Isso geraria as primeiras 4.000.000 linhas na saída padrão - você provavelmente deseja anexar outro canal para realmente fazer algo com os dados.

Para obter as outras partes, você usaria uma combinação de heade tail, como:

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

para obter o segundo bloco.

Talvez uma série dessas seja uma solução ou o gunzip -c exigiria espaço suficiente para que o arquivo inteiro fosse descompactado

Não, gunzip -cnão requer espaço em disco - ele faz tudo na memória e depois transmite para stdout.


Se você quiser criartodas as peças de uma só vez, é mais eficiente criá-los todos com um único comando, pois assim o arquivo de entrada só é lido uma vez. Uma boa solução é usar split; veja a resposta de Jim Mcnamara para obter detalhes.

Responder2

pipe para dividir use gunzip -c ou zcat para abrir o arquivo

gunzip -c bigfile.gz | split -l 400000

Adicione especificações de saída ao comando split.

Responder3

Como você está trabalhando em um fluxo (não rebobinável), você desejará usar a forma '+N' de cauda para obter linhas começando da linha N em diante.

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

Responder4

Divida diretamente o arquivo .gz em arquivos .gz:

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

Acho que era isso que o OP queria, porque ele não tem muito espaço.

informação relacionada