有时候会需要对大文件进行并行处理,但是perl中不像其他的语言,可以使用多线程,perl的多线程其实就是对文件进行切割;
而对于文本文件,需要保证行的完整性,一种是快速跳过不需要的行:
#!/usr/bin/perl -w
use strict;
no warnings 'recursion';
my $m=$ARGV[0]; #分成m份
my $l=$ARGV[1]; #第l份
my $file="test1.txt";
my $line=`wc -l $file`;
my ($linenum)=$line=~/(\d+)/;
my $linenum=10 if(!($linenum));
my $n=int($linenum/$m); #每份做n行
open READ, "$file" || die $!;
my $i=0;
while (<READ>) {
if ($i>=($l-1)*$n){&doit();}
$i++;
last if ($i>=$l*$n || $i>linenum)
}
sub doit(){
print $_;
}
close READ;
好一点的办法是使用seek,但是需要处理不完整行,可以让前一个进程多处理一行,后一个进程少处理一行:
#!/usr/bin/perl -w
use strict;
no warnings 'recursion';
my $m=$ARGV[0]; #分成m份
my $l=$ARGV[1]; #第l份
my $file="test1.txt";
my @args = stat $file;
my $size = $args[7];
my $n=int($size/$m); #每份做nbytes
open READ, "<$file" || die $!;
seek READ,(($l-1)*$n),0;
#非第一份,少读第一行
if($l>1){
my $tmpline = <READ>;
}
while (<READ>) {
&doit();
my $position = tell(READ);
last if ($position> $l*$n || $position>=$size); #多读一行
}
sub doit(){
print $_;
}
close READ;
perl大文件读取处理模块
perl CPAN里面的 Tie-File 模块极大方便了对大文件的操作。该模块用perl的数组代表一个文件,文件的每一行对应数组的一个元素,第一行为元素0,第二回为1,... 文件本身实际并不加载到内存,对数组元素的操作立刻作用到文件里。
最大的方便是可以任意指定处理开头结尾的某几行。
Tie-File 模块的基本用法:
#!/usr/bin/perl -w
use strict;
no warnings 'recursion';
use Tie::File;
tie @array, 'Tie::File', filename or die ...;
$array[13] = 'blah'; # line 13 of the file is now 'blah'
print $array[42]; # display line 42 of the file
$n_recs = @array; # how many records are in the file?
$#array -= 2; # chop two records off the end
foreach (@array) {
s/PERL/Perl/g; # Replace PERL with Perl everywhere in the file
}
# These are just like regular push, pop, unshift, shift, and splice
# Except that they modify the file in the way you would expect
push @array, new recs...;
my $r1 = pop @array;
unshift @array, new recs...;
my $r2 = shift @array;
@old_recs = splice @array, 3, 7, new recs...;
untie @array; # all finished
还有一个是Perl中的Thread模块:
http://doc.plob.org/perl/perl/PerlThread.html#17_2_1