$rvsfile
是文件的路径大约200M。我想计算其中$userid
的行数。但是在while循环中使用grep
似乎非常缓慢。那么有没有有效的方法来做到这一点?由于$rvsfile
非常大,我无法使用@tmp = <FILEHANDLE>
将其读入内存。
while(defined($line = <SRCFILE>))
{
$line =~ /^([^\t]*)\t/;
$userid = $1;
$linenum = `grep '^$userid\$' $rvsfile | wc -l`;
chomp($linenum);
print "$userid $linenum\n";
if($linenum == 0)
{
print TARGETFILE "$line";
}
}
如何在没有\t
的行中regex
之前获取该部分?例如,该行可能是这样的:
2013123 \t
的东西
如果没有正则表达式,我怎样才能获得2013123
答案 0 :(得分:3)
是的,你是在每个循环调用上分配一个shell。这很慢。您还可以为每个用户阅读整个$rsvfile
一次。这太过分了。
SRCFILE
一次并构建@userids
。$rvsfile
。草图:
my @userids;
while(<SRCFILE>)
{
push @userids, $1 if /^([^\t]*)\t/;
}
my $regex = join '|', @userids;
my %count;
while (<RSVFILE>)
{
++$count{$1} if /^($regex)$/o
}
# %count has everything you need...
答案 1 :(得分:1)
答案 2 :(得分:1)
如果我正确地读了你,你想要这样的东西:
#!/usr/bin/perl
use strict;
use warnings;
my $userid = 1246;
my $count = 0;
my $rsvfile = 'sample';
open my $fh, '<', $rsvfile;
while(<$fh>) {
$count++ if /$userid/;
}
print "$count\n";
甚至,(如果我错了,有人会纠正我,但这并不认为这会读取整个文件):
#!/usr/bin/perl
use strict;
use warnings;
my $userid = 1246;
my $rsvfile = 'sample';
open my $fh, '<', $rsvfile;
my $count = grep {/$userid/} <$fh>;
print "$count\n";
答案 3 :(得分:1)
如果<SRCFILE>
相对较小,你可以反过来做。一次读取一行中的较大文件,并检查每行的每个用户ID,使用散列结构保留每个用户ID的计数。类似的东西:
my %userids = map {($_, 0)} # use as hash key with init value of 0
grep {$_} # only return mataches
map {/^([^\t]+)/} <SRCFILE>; # extract ID
while (defined($line = <LARGEFILE>)) {
for (keys %userids) {
++$userids{$_} if $line =~ /\Q$_\E/; # \Q...\E escapes special chars in $_
}
}
这样,只重复读取较小的数据,扫描大文件一次。最终得到每个用户标识的哈希值,该值是它出现的行数。
答案 4 :(得分:1)
使用哈希:
my %count;
while (<LARGEFILE>) {
chomp;
$count{$_}++;
};
# now $count{userid} is the number of occurances
# of $userid in LARGEFILE
或者,如果您担心为哈希使用太多内存(即您对6个用户感兴趣,并且大文件中还有100K以上),请以另一种方式执行此操作:
my %count;
while (<SMALLFILE>) {
/^(.*?)\t/ and $count{$_} = 0;
};
while (<LARGEFILE>) {
chomp;
$count{$_}++ if defined $count{$_};
};
# now $count{userid} is the number of occurances
# of $userid in LARGEFILE, *if* userid is in SMALLFILE
答案 5 :(得分:0)
如果您有选择,请尝试使用awk
awk 'FNR==NR{a[$1];next} { for(i in a) { if ($0 ~ i) { print $0} } } ' $SRCFILE $rsvfile