解析Perl中的大文件

时间:2012-11-19 10:54:24

标签: perl file

我需要将包含2200万行的大文件(2GB)与另一个文件进行比较。在使用Tie :: File时我花了更多的时间来处理它。所以我已经通过'while'完成了它,但问题仍然存在。看下面的代码......

use strict;
use Tie::File;
# use warnings;
my @arr;
# tie @arr, 'Tie::File', 'title_Nov19.txt';

# open(IT,"<title_Nov19.txt");                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
# my @arr=<IT>;
# close(IT);
open(RE,">>res.txt");

open(IN,"<input.txt");

while(my $data=<IN>){
    chomp($data);
    print"$data\n";
    my $occ=0;

    open(IT,"<title_Nov19.txt");    
    while(my $line2=<IT>){

        my $line=$line2;
        chomp($line);

        if($line=~m/\b$data\b/is){

            $occ++;

        }

    }
print RE"$data\t$occ\n";
}


close(IT);
close(IN);
close(RE);

所以帮我减少它......

4 个答案:

答案 0 :(得分:2)

这有很多不妥之处。

除了通常的(缺少use strictuse warnings,使用2参数open(),不检查open()结果,使用全局文件句柄),具体在您的情况下,问题是您为第一个文件的每一行打开/读取/关闭第二个文件。这将非常缓慢。

我建议您打开文件title_Nov19.txt一次,将所有行读入数组或哈希或其他内容,然后关闭它;然后你可以打开第一个文件input.txt并沿着那个文件进行比较,与数组中的内容进行比较,这样你就不必一直重新打开第二个文件。

我建议你阅读一些关于风格/等的基本文章。因为如果你的问题实际上是用模糊的现代标准写的,你的问题可能会得到更多关注。

答案 1 :(得分:0)

我尝试构建一个具有更好结构的小示例脚本,但我不得不说,男人,你的问题描述真的很不清楚。每次@LeoNerd在答案中解释时,读取整个比较文件非常重要。然后我使用哈希来跟踪匹配计数:

#!/usr/bin/env perl

use strict;
use warnings;

# cache all lines of the comparison file
open my $comp_file, '<', 'input.txt' or die "input.txt: $!\n";
chomp (my @comparison = <$comp_file>);
close $comp_file;

# prepare comparison
open my $input,  '<', 'title_Nov19.txt' or die "title_Nov19.txt: $!\n";
my %count = ();

# compare each line
while (my $title = <$input>) {
    chomp $title;

    # iterate comparison strings
    foreach my $comp (@comparison) {
        $count{$comp}++ if $title =~ /\b$comp\b/i;
    }
}

# done
close $input;

# output (sorted by count)
open my $output, '>>', 'res.txt' or die "res.txt: $!\n";
foreach my $comp (@comparison) {
    print $output "$comp\t$count{$comp}\n";
}
close $output;

只是为了让你开始...如果有人想进一步研究这些:这些是我的测试文件:

<强> title_Nov19.txt

This is the foo title
Wow, we have bar too
Nothing special here but foo
OMG, the last title! And Foo again!

<强> input.txt中

foo
bar

该程序的结果写入 res.txt

foo 3
bar 1

答案 2 :(得分:0)

这是使用memowe(谢谢)数据的另一个选项:

use strict;
use warnings;
use File::Slurp qw/read_file write_file/;

my %count;
my $regex = join '|', map { chomp; $_ = "\Q$_\E" } read_file 'input.txt';

for ( read_file 'title_Nov19.txt' ) {
    my %seen;
    !$seen{ lc $1 }++ and $count{ lc $1 }++ while /\b($regex)\b/ig;
}

write_file 'res.txt', map "$_\t$count{$_}\n",
  sort { $count{$b} <=> $count{$a} } keys %count;

按数字排序的输出到res.txt

foo 3
bar 1

构建并使用引用元字符(\Q$_\E)的交替正则表达式,因此只需要对大文件的行进行一次传递。哈希%seen用于确保输入的单词每行只计算一次。

希望这有帮助!

答案 3 :(得分:0)

试试这个:

grep -i -c -w -f input.txt title_Nov19.txt&gt; res.txt