#!/usr/bin/perl use Algorithm::Diff; my ($len, $off, $file1, $file2) = @ARGV; $len or die "Usage: $0 "; my ($buf1, $buf2); open ONE, $file1 or die "$file1: $!"; read(ONE, $buf1, $len, $off); open TWO, $file2 or die "$file2: $!"; read(TWO, $buf2, $len, $off); @buf1 = split //, $buf1; @buf2 = split //, $buf2; my $diff = Algorithm::Diff->new(\@buf1, \@buf2); @differences; while ($diff->Next) { if ($diff->Same and $diff->Items(1) > 3 ) { clear_difference_buffer(); print_same($diff); } else { if (!@differences) { push @differences, [$diff->Get(qw( Min1 Max1 Min2 Max2 )) ] } push @differences, [ $diff->Items(1), $diff->Items(2) ]; } } sub print_position { my ($min1, $max1, $min2, $max2) = @_; if ($min1 == $min2 and $max1 == $max2) { printf "%d-%d : ", $min1+$off, $max1+$off; } else { printf "%d-%d / %d-%d: ", $min1+$off, $max1+$off, $min1+$off, $max2+$off; } } sub printable { my $string = shift; my $in_len = length($string); $string =~ s/([^[:print:]]|\s)/sprintf("\\x{%x}", ord($1))/eg; $in_len > 1 ? "[$string]" : $string; } sub print_same { my $d = shift; print_position($d->Get(qw( Min1 Max1 Min2 Max2 ))); my $stuff = join "", $d->Items(1); print length($stuff), " identical characters"; print ": ", printable($stuff) if length($stuff) < 40; print "\n"; } sub clear_difference_buffer { return unless @differences; my @offsets = @{ shift @differences }; my ($left, $right); for (@differences) { $left .= $_->[0]; $right .= $_->[1]; } $offsets[1] += length($left); $offsets[3] += length($right); print_position(@offsets); if (length($left) != length($right)) { print length($left), " / " , length($right); } else { print length($left) } print " different characters"; my ($p_left, $p_right) = (printable($left), printable($right)); if (length($p_left.$p_right) < 40) { print ": $p_left versus $p_right"; } print "\n"; @differences = (); }