Подробности моего запроса приведены ниже:
- У меня есть очень большой файл TSV (Tab Sep. Value) (где большой> 30 ГБ).
- Я хочу извлечь из этого файла определенные строки, которые не заканчиваются пустым последним полем. Поскольку это файл TSV, эти строки не заканчиваются
\t\n
, что является тривиальным тестом и не является предметом этого вопроса. Это удалит около 75% линий, сразу же, уменьшив нагрузку.
- Затем я хочу извлечь небольшое подмножество полей из оставшихся строк. Поля не являются смежными, но их немного (например, скажем, семь из чуть более тридцати в общей сложности). Например, скажем, поля
2,3,12-18,25-28,31
.
- Строки, из которых я извлекаю, очень длинные, большинство длиной до 1000 символов, поскольку они содержат большое количество полей с разделителями табуляции.
Один из вариантов - это, очевидно, использовать следующий простой код, который я попытался красиво отформатировать и включить комментарии, чтобы показать мои рассуждения:
use warnings;
use strict;
# I am using the latest stable version of Perl for this exercise
use 5.30.0;
while (<>)
{
# Skip lines ending with an empty field
next if substr($_,-2) eq "\t\n";
# Remove "\n"
chomp;
# Split matching lines into fields on "\t", creating @fields
my @fields=split(/\t/,$_);
# Copy only the desired fields from @fields to create a new
# line in TSV format
# This can be done in one simple step in Perl, using
# array slices and the join() function
my $new_line=join("\t",@fields[2,3,12..18,25..28,31]);
# ...
}
Но использование split
приводит к дополнительному анализу (за исключением последнего поля, которое мне нужно) и создает полный массив полей, которые мне также не нужны. Я думаю, что было бы эффективнее не создавать массив, а анализировать каждую строку, искать вкладки и подсчитывать индексы полей по ходу, создавать выходную строку на пути и останавливаться на последнем нужном поле.
Правильно ли я оцениваю или просто делаю простой split
, за которым следует join
срезов, содержащих интересующие вас поля, лучший способ добраться сюда с точки зрения производительности?
Обновление : К сожалению, никто не упомянул о возможности использования GNU cut
для разделения и передачи результатов в Perl для остальной части обработки. Это, вероятно, самый эффективный способ, без написания большого количества пользовательского (C) кода для этого или обращения к чтению на основе больших блоков с пользовательским разбором строк (также в C).