Я уверен, что у кого-то была следующая потребность, как быстро разбить огромный файл .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'
Я думаю, именно этого и хотел автор поста, потому что у него не так много места.