0

我需要将包含 2200 万行的大文件(2GB)与另一个文件进行比较。在使用 Tie::File.so 时需要更多时间来处理它。所以我已经通过'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

4 回答 4

2

很多事情都错了。

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

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

此外,我建议您阅读一些有关样式/等的基本文章。如果您的问题实际上是用模糊的现代标准编写的,那么您的问题可能会受到更多关注。

于 2012-11-19T10:59:12.570 回答
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!

输入.txt

foo
bar

程序的结果被写入res.txt

foo 3
bar 1
于 2012-11-19T11:42:25.640 回答
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用于确保输入单词每行只计算一次。

希望这可以帮助!

于 2012-11-19T20:19:31.820 回答
0

尝试这个:

grep -i -c -w -f input.txt title_Nov19.txt > res.txt

于 2018-03-13T01:21:01.797 回答