unix - разбить большой файл .gz по строкам

unix - разбить большой файл .gz по строкам

Я уверен, что у кого-то была следующая потребность, как быстро разбить огромный файл .gz по строкам? Базовый текстовый файл содержит 120 миллионов строк. У меня недостаточно места на диске, чтобы сжать весь файл сразу, поэтому мне было интересно, знает ли кто-нибудь скрипт или инструмент bash/perl, который мог бы разбить файл (либо .gz, либо внутренний .txt) на 3 файла по 40 миллионов строк. Например, вызвав его так:

    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

чтобы получить второй блок.

Возможно, решение состоит в выполнении ряда таких действий или gunzip -c потребует достаточно места для распаковки всего файла?

Нет, ему gunzip -cне требуется дисковое пространство — он все делает в памяти, а затем выводит данные на стандартный вывод.


Если вы хотите создатьвсе части за один раз, эффективнее создать их все одной командой, потому что тогда входной файл читается только один раз. Одним из хороших решений является использование split; см. ответ Джима Макнамары для получения подробной информации.

решение2

для разделения используйте gunzip -c или zcat для открытия файла

gunzip -c bigfile.gz | split -l 400000

Добавьте выходные характеристики к команде split.

решение3

Поскольку вы работаете с потоком (неперематываемым), вам понадобится использовать форму «+N» для хвоста, чтобы получить строки, начиная со строки 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'

Я думаю, именно этого и хотел автор поста, потому что у него не так много места.

Связанный контент