Perl читает только определенные строки файла gz - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь создать скрипт синтаксического анализа, который анализирует огромный текстовый файл (более 2 миллионов строк), сжатый с помощью gunzip.Я только хочу проанализировать диапазон строк в текстовом файле.До сих пор я использовал zgrep -n, чтобы найти две строки, в которых упоминается строка, которая, как я знаю, будет начинать и заканчивать интересующий меня раздел файла.

В моем файле тестового примера, который меня интересует,только чтение в строках с 123080 по 139361. Я нашел Tie :: File для доступа к строкам файла с помощью возвращаемого объекта массива, но, к сожалению, это не сработает для сжатого файла с оружием, с которым я работаю.

Есть ли что-то вроде следующего для заархивированного файла?

use Tie::File
tie @fileLinesArray, 'Tie::File', "hugeFile.txt.gz"
my $startLine = 123080;

my $endLine = 139361;    
my $lineCount = $startLine;
while ($lineCount <= $endLine){
    my $line = @fileLinesArray[$lineCount]
    blah blah...
}

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

Использование IO :: Uncompress :: Gunzip , который является основным модулем:

use IO::Uncompress::Gunzip;

my $z = IO::Uncompress::Gunzip->new('file.gz');
$z->getline for 1 .. $start_line - 1;
for ($start_line .. $end_line) {
    my $line = $z->getline;
    ...
}

Tie :: File становится очень медленным и требует много памяти при обработкебольшие файлы.

0 голосов
/ 08 декабря 2018

Вы пишете: " В моем файле тестового примера меня интересует только чтение в строках с 123080 по 139361 ".

Это также можно сделать в оболочке:

zcat file | tail -n +123080 | head -16282

Или:

my $file = 'the_file.gz';
my($from,$to) = (123080,139361);
my @lines = qx( zcat $file | tail -n +$from | head -@{[-$from+$to+1]});

Это может быть быстрее, чем обычное одноядерное чистое Perl-решение, поскольку zcat, tail и head внутри qx станут тремя процессами,и Perl четвертый.И все четыре могут получить отдельное ядро ​​процессора самостоятельно.Возможно, вы захотите проверить скорость с разными номерами строк.

0 голосов
/ 06 декабря 2018

Tie::File - плохая идея для больших файлов, так как необходимо хранить весь файл в памяти сразу.Это также непрактичная, если не невозможная идея для сжатых файлов.Вместо этого вы захотите работать с потоком ввода ваших данных.И если вы собираетесь изменить данные, выходной поток в новую копию данных.Perl имеет довольно хорошую поддержку сжатия gzip с помощью процессов PerlIO::gzip' layer, but you could also pipe data through one or two gzip`.

# I/O stream initialization
use PerlIO::gzip;
open my $input, "<:gzip", "data.gz";
open my $output. ">:gzip", "data.new.gz";    # if $output is needed

# I/O stream initialization without PerlIO::gzip
open my $input, "gzip -d data.gz |";
open my $output, "| gzip -c > data.new.gz";

После настройки входных (и необязательных выходных) потоков вы можете использовать на них средства ввода-вывода Perl простокак и любые другие файловые дескрипторы.

# copy first $startLine lines unedited
while (<$input>) {
    print $output $_;
    last if $. >= $startLine;
}

while (my $line = <$input>) {
    # blah blah blah
    # manipulate $line
    print $output $line;
    last if $. >= $endLine;
}

print $output <$input>; # write remaining input to output stream
close $input;
close $output;
...