2

我有2个文件,即

**a.txt**
cars
bikes
bus 
vehicle
atv

**b.txt**
hawk
hero
atv
bus

***result.txt***
cars
bikes
vehicle
hawk
hero

我想打印两个文件之间的差异。现在我尝试了一个代码,但它以随机的方式给了我差异;我希望它以正确的顺序方式显示它。任何人都可以帮我解决这个问题。

use strict;
my %results = ();  

open FILE1, "<a.txt"
    or die "Could not open file: $! \n"; 
while (my $line = <FILE1>) {

    $results{$line}=1; 
} 
close FILE1;  

open FILE2, "<b.txt" 
    or die "Could not open file: $! \n"; 
while (my $line = <FILE2>) {

    $results{$line}++; 
} 
close FILE2;

open OUTFILE, ">>result.txt" 
    or die "Cannot open $outfile for writing \n";
foreach my $line (keys %results) { 

    print OUTFILE $line if $results{$line} == 1; 
} 

close OUTFILE; 
close OUTFILE1;

我用这段代码得到的输出是

***result.txt***
cars
hawk
bikes
hero
vehicle
4

4 回答 4

5

哈希以随机顺序存储它们的元素,因此我们必须随身携带位置信息。在下面的解决方案中,我使用哈希值来携带唯一的 ID。

代码

#!/usr/bin/perl
use strict; use warnings; use Data::Dumper;

my @a = qw( cars bikes bus vehicle atv );
my @b = qw( hawk hero atv bus );

my $i = 0;
my %ahash = map {$_ => ++$i} @a;
my %bhash = map {$_ => ++$i} @b;

my %different = map {
  ($ahash{$_} and $bhash{$_})
    ? ()
    : ($_ => ($ahash{$_} or $bhash{$_}))
} (keys %ahash, keys %bhash);

my @sorted = sort {$different{$a} <=> $different{$b}} keys %different;

print Dumper(\@sorted);

讨论

出于演示的目的,我没有使用文件,而是将记录存储在数组@a@b.

我从这些数组构建散列%ahash%bhash使用数组元素作为键并使用唯一的数字作为值。在 的情况下%ahash,这些 ID 与行号相同。您可以将其中的 ID%bhash视为带有偏移量的行号。

然后我收集哈希之间不同的所有键值对。为此,我列出了%ahash和中的所有键%bhash。对于这些键中的每一个,我在两个散列中测试该键的存在(我不使用exists,而是针对该值进行测试,因为我可以保证没有分配具有 false 值的 ID - 除了0评估为 true之外的所有数字)。如果密钥在两个哈希中都存在,则返回空列表()。如果键仅存在于其中一个哈希中,则返回一个包含键和值的二元素列表,该列表位于 in%ahash或中%bhash

在下一步中,我按关联值对所有不同的键进行升序排序,并将这些键按此顺序存储在@sorted. 您可以将它们打印到文件中,我只是将它们转储,然后得到以下输出:

$VAR1 = [
      'cars',
      'bikes',
      'vehicle',
      'hawk',
      'hero'
    ];

我相信这符合您的标准。

基本上,您有一个非常优雅的算法来查找差异,但是您没有合并排序数据,就像我对行号之类的 ID 所做的那样。

风格注释

在大多数情况下,使用词法文件句柄 withmy优于使用全局文件句柄。此外,三参数形式的open更灵活,值得习惯。例如,我会把你的第三行写成

my $filename1 = "a.txt";
open my $file1, '<', $filename1 or die qq{Could not open "$filename1": $!\n};

但话又说回来,TIM TOWTDI。

于 2012-09-18T04:44:11.943 回答
1
perl -lne '$X{$_}++;if(eof){$a++;}if($a==2){foreach (keys %X){if($X{$_}==1){print $_}}}' file1 file2

测试如下:

> cat temp
cars
bikes
bus
vehicle
atv
> cat temp2
hawk
hero
atv
bus
> perl -lne '$X{$_}++;if(eof){$a++;}if($a==2){foreach (keys %X){if($X{$_}==1){print $_}}}' temp temp2
cars
hawk
hero
vehicle
bikes
>
于 2012-09-18T07:02:53.547 回答
0

由于数据存储为哈希引用,因此不保留顺序。请参阅如何按特定顺序打印 Perl 哈希?

于 2012-09-18T03:42:59.153 回答
0
$ diff a.txt b.txt

$ 不是代码的一部分,它用于表示 bash 命令提示符。

comm 也可能对您有用。

于 2012-09-20T10:11:53.247 回答