use strict; use warnings; use IO::File; # this script takes a sequence of phandle outputs, and determines what # handles have been added/removed between each phandle-output. my @f; for my $fn (@ARGV) { push @f, readfile($fn); } my @r; for my $i (1..$#f) { my ($nota, $notb)= diff($f[$i-1], $f[$i]); if (@r) { my $isec= intersection($r[-1], $notb); substract($r[-1], $isec); substract($notb, $isec); } push @r, $notb; push @r, $nota; } for my $i (0..$#r) { printf("\n%s:\n", ($i&1)?"added":"removed"); print map { sprintf("%s %s\n", $_, $r[$i]{$_}) } keys %{$r[$i]}; } sub readfile { my ($fn)= @_; my $fh= IO::File->new($fn, "r") or die "$fn: $!\n"; my %l; while (<$fh>) { s/[\r\n\s]+$//; if (/^(\w+ .... -> \w+ : \w+) (.*)/) { $l{$1}=$2; } } return \%l; } sub substract { my ($s1, $s2)= @_; for my $k (keys %$s2) { delete $s1->{$k}; } } sub intersection { my ($s1, $s2)= @_; my %x; for my $k (keys %$s2) { if (exists $s1->{$k}) { if ($s2->{$k} eq $s1->{$k}) { $x{$k}= $s1->{$k}; } else { $x{$k}= $s1->{$k}." changed to ".$s2->{$k}; } } } return \%x; } sub diff { my ($f1, $f2)= @_; my %notf1; my %notf2; for my $k (keys %$f1) { if (!exists $f2->{$k}) { $notf2{$k}=$f1->{$k}; } } for my $k (keys %$f2) { if (!exists $f1->{$k}) { $notf1{$k}=$f2->{$k}; } } return (\%notf1, \%notf2); }