1

我通常在 perl 中使用 awk 来区分两个文件,如下所示。

my @awkoutput = system("awk 'NR == FNR { A[\$0]=1; next } !A[\$0]' file1.txt file2.txt");

但是,是否可以在两个 perl 数组之间进行类似的差异?

我不认为这是可能的。我们可能必须将所有 perl 数组元素移动到文件中并执行此操作。我试图找到的只是做差异而不创建文件。

4

1 回答 1

11

鉴于:

my @array1 = ( "abc", "def", "ghi", "jkl" );
my @array2 = ( "xyz", "abc", "jkl", "mnp" );

其中填充了本来会写入file1.txtand的数据file2.txt,然后您可以将您的音译awk为 Perl:

{
    my %file1;
    foreach (@array1) { $file1{$_} = 1; }
    foreach (@array2) { print $_ unless $file1{$_}; }
}

大括号确保%file1仅持续该代码块。对于给定的数组,该代码输出:

xyz
mnp

即使数组是 100 MiB 的数据,它也不可能比写入两个文件并调用awk它们慢。

定时

您使用哪种机器需要一分钟来处理数据?这是上面脚本的一个简单的修改。我在其他相似的行中生成了两个带有随机数的文件,其中随机数的范围重叠。

$ random -F "The random line contains %d to make it different sometimes" -n 1000000 1 999999 > file1.txt
$ random -F "The random line contains %d to make it different sometimes" -n 1000000 500000 1499999 > file2.txt
$ time perl x3.pl > file3.txt

real    0m2.983s
user    0m2.642s
sys     0m0.332s
$ wc -l file?.txt
 1000000 file1.txt
 1000000 file2.txt
  683637 file3.txt
 2683637 total
$ ls -l file?.txt
-rw-r--r--  1 jleffler  eng  62888452 Oct 15 08:14 file1.txt
-rw-r--r--  1 jleffler  eng  63500365 Oct 15 08:15 file2.txt
-rw-r--r--  1 jleffler  eng  43569496 Oct 15 08:17 file3.txt
$ time awk 'NR == FNR { A[$0]=1; next } !A[$0]' file1.txt file2.txt > file4.txt

real    0m3.853s
user    0m3.670s
sys     0m0.174s
$ cmp file[34].txt
$

这是在具有 16 GiB 内存和 SSD 的 MacBook Pro 上运行的,但即便如此,Perl 读取两个 60+ MiB 文件并产生差异的时间不到 3 秒,相比之下,只用awk了不到 4 秒。

脚本

#!/usr/bin/perl
use strict;
use warnings;

open my $f1, '<', 'file1.txt' or die;
my @array1 = <$f1>;
open my $f2, '<', 'file2.txt' or die;
my @array2 = <$f2>;

{
my %file1;
foreach (@array1) { $file1{$_} = 1; }
foreach (@array2) { print "$_" unless $file1{$_}; }
}
于 2013-10-15T15:09:35.513 回答