是否可以使用awk来区分两个perl数组?

时间:2013-10-15 14:49:31

标签: arrays perl awk

我通常在perl中使用awk在两个文件之间做差异,如下所示。

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

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

我认为不可能。我们可能必须将所有perl数组元素移动到文件并执行它。我想要找的就是做差异而不创建文件。

1 个答案:

答案 0 :(得分:11)

假设:

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

,其中填充了原本将写入file1.txtfile2.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花了不到3秒的时间来读取这两个60+ MiB文件并产生差异,相比之下,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{$_}; }
}