从Perl中的大文件中读取特定行

时间:2011-12-18 10:59:15

标签: perl file line

是否有任何快速且内存有效的方法来读取大文件的特定行,而不将其加载到内存中?

我写了一个perl脚本,它运行许多forks,我希望他们从文件中读取特定的行。

目前我正在使用外部命令:

sub getFileLine {
    my ( $filePath, $lineWanted ) = @_;
    $SIG{PIPE} = '_IGNORE_';
    open( my $fh, '-|:utf8', "tail -q -n +$lineWanted \"$filePath\" | head -n 1" );
    my $line = <$fh>;
    close $fh;
    chomp( $line );
    return $line;
}

它的速度很快而且很有效 - 但也许有更多的“Perl-ish”方式,与这个一样快速和内存效率?

如您所知,在Perl中创建fork进程会复制主进程内存 - 因此如果主进程使用10MB,则fork将使用至少那么多。

我的目标是保持fork进程(所以主要进程直到运行forks)内存使用尽可能低。这就是为什么我不想将整个文件加载到内存中。

3 个答案:

答案 0 :(得分:17)

在进一步了解之前,了解fork的工作原理非常重要。当您fork进程时,操作系统使用copy-on-write语义来共享大部分父进程和子进程&#39;记忆;只需要单独分配父和子之间不同的内存量。

要在Perl中读取文件的一行,这里有一个简单的方法:

open my $fh, '<', $filePath or die "$filePath: $!";
my $line;
while( <$fh> ) {
    if( $. == $lineWanted ) { 
        $line = $_;
        last;
    }
}

这使用特殊的$.变量,该变量保存当前文件句柄的行号。

答案 1 :(得分:4)

查看Tie::File核心模块。

答案 2 :(得分:0)

你不需要分叉。您可以想象,从文件中读取特定行是一项非常常见的操作,CPAN上的20k模块之一就已经完成。

File::ReadBackwards具有内存效率和速度。