Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Array::Compare issues

by sunadmn (Curate)
on Oct 03, 2003 at 19:21 UTC ( #296364=perlquestion: print w/ replies, xml ) Need Help??
sunadmn has asked for the wisdom of the Perl Monks concerning the following question:

Good day all I have a script that is using Array::Compare and for some reason when I print the output of the compare I am getting a slew of numbers instead of the actaul lines that are different in the two files.

Below is a copy of my code and the output file if anyone can help with this one please do I am lost.
#!/usr/bin/perl -w use Array::Compare; use strict; my $file1 = "/var/tmp/db.bind1"; my $file2 = "/var/tmp/db.bind2"; my $out = "/var/tmp/compare_out"; open(FILE1, "$file1") || die "Can't open $file1 to read\nReason: $!\n +"; my @file1 = <FILE1>; close(FILE1); open(FILE2, "$file2") || die "Can't open $file2 to read\nReason: $!\n +"; my @file2 = <FILE2>; close(FILE2); open(OUT, ">$out") || die "Cant create $out\nReason: $!\n"; my $comp = Array::Compare->new(DefFull => 1); #$comp->compare(\@file1, \@file2); print OUT $comp->full_compare(\@file1,\@file2); close(OUT); exit;
Here is the output file:
# more compare_out 3945739458394593946039461394623946339464394653946639467394683946939470 +394713947239473394743947539476394773947839479394803948139482394833948 +439485394863948739488394893949039491394923949339494394953949639497394 +983949939500395013950239503395043950539506395073950839509395103951139 +512395133951439515395163951739518395193952039521395223952339524395253 +952639527395283952939530395313953239533395343953539536395373953839539 +395403954139542395433954439545395463954739548395493955039551395523955 +339554395553955639557395583955939560395613956239563395643956539566395 +673956839569395703957139572395733957439575395763957739578395793958039 +581395823958339584395853958639587395883958939590395913959239593395943 +959539596395973959839599396003960139602396033960439605396063960739608 +396093961039611396123961339614396153961639617396183961939620396213962 +239623396243962539626396273962839629396303963139632396333963439635396 +363963739638396393964039641396423964339644396453964639647396483964939 +650396513965239653396543965539656396573965839659396603966139662396633 +966439665396663966739668396693967039671396723967339674396753967639677 +396783967939680396813968239683396843968539686396873968839689396903969 +139692396933969439695396963969739698396993970039701397023970339704397 +053970639707397083970939710397113971239713397143971539716397173971839 +719397203972139722397233972439725397263972739728397293973039731397323 +973339734397353973639737397383973939740397413974239743397443974539746 +397473974839749397503975139752397533975439755397563975739758397593976 +039761397623976339764397653976639767397683976939770397713977239773397 +74

Comment on Array::Compare issues
Select or Download Code
Re: Array::Compare issues
by jdtoronto (Prior) on Oct 03, 2003 at 19:34 UTC
    Um, so am I!

    I take it you want Array::Compare to return the ACTUAL differences between the two arrays? If that is so then you are out of luck, but I am likely to be wrong! According to the module docs:

      In addition to the simple comparison described above (which returns true if the arrays are the same and false if they're different) there is also a full comparison which returns a list of elements which are different. If the arrays are the same it returns an empty list. In scalar context the full comparison returns the length of this list (i.e. the number of elements that differ). You can access the full comparision in two ways. Firstly, there is a DefFull attribute. If this is true then a full comparison if carried out whenever the compare method is called.
    So it will return either the number of differences in a SCALAR contect or a list of the elements which differ, whioch in my reading would be a list of the element references. It seems that you are seeing the flattened list and you should treat the return value as a list and see what it contains.

    Of course this would be vastly easier if you gave us two small test arays to look at! Could you perhaps include the input array data in a DATA block so we can play with it?

    jdtoronto

      here you go this is a sample of my array contents for @array1
      /usr/share/release_info/Solaris_8/C/S8FCSreleasenotes /usr/share/lib/pub/UTF-8 /usr/share/lib/pub/ascii /usr/share/lib/pub/eqnchar /usr/share/lib/pub/greek /usr/share/lib/pub/iso /usr/share/lib/setterm/en_US.UTF-8/conf.file /usr/share/lib/mailx/mailx.help /usr/share/lib/mailx/mailx.help.~ /usr/share/lib/tabset/3101 /usr/share/lib/tabset/beehive /usr/share/lib/tabset/hds /usr/share/lib/tabset/hds3 /usr/share/lib/tabset/std /usr/share/lib/tabset/stdcrt /usr/share/lib/tabset/teleray /usr/share/lib/tabset/vt100 /usr/share/lib/tabset/wyse-adds /usr/share/lib/tabset/xerox1720 /usr/share/lib/terminfo/3/386AT /usr/share/lib/terminfo/3/386AT-M /usr/share/lib/terminfo/3/386at /usr/share/lib/terminfo/3/386at-m /usr/share/lib/terminfo/3/300 /usr/share/lib/terminfo/3/3045 /usr/share/lib/terminfo/3/31 /usr/share/lib/terminfo/3/3101
      And here is @file2 sample content.
      /usr/share/release_info/Solaris_8/C/S8FCSreleasenotes /usr/share/lib/pub/UTF-8 /usr/share/lib/pub/ascii /usr/share/lib/pub/eqnchar /usr/share/lib/pub/greek /usr/share/lib/pub/iso /usr/share/lib/setterm/en_US.UTF-8/conf.file /usr/share/lib/mailx/mailx.help /usr/share/lib/mailx/mailx.help.~ /usr/share/lib/tabset/3101 /usr/share/lib/tabset/beehive /usr/share/lib/tabset/hds /usr/share/lib/tabset/hds3 /usr/share/lib/tabset/std /usr/share/lib/tabset/stdcrt /usr/share/lib/tabset/teleray /usr/share/lib/tabset/vt100 /usr/share/lib/tabset/wyse-adds /usr/share/lib/tabset/xerox1720 /usr/share/lib/terminfo/3/386AT /usr/share/lib/terminfo/3/386AT-M
      Basiclly what I am trying to get out of this is a quicker way to build packages for Solaris boxes. With that said the output we want is just the differences in the two files. @file1 is an array of what was in /usr prior to the compile and make install of the software. @file2 is a list of /usr after the compile ad make install. Now it would sound easier to just use "sdiff" , but the issue I have ran into is that when you run sdiff you get output that looks like this
      /usr/local/lib/security/libgcj.security /us +r/local/lib/security/libgcj.security > /us +r/local/lib/libisc.so.7.0.0 > /us +r/local/lib/libisc.la > /us +r/local/lib/libisc.a > /us +r/local/lib/libisccc.so.0.1.0 > /us +r/local/lib/libisccc.la > /us +r/local/lib/libisccc.a > /us +r/local/lib/libdns.so.11.0.1 > /us +r/local/lib/libdns.la > /us +r/local/lib/libdns.a > /us +r/local/lib/libisccfg.so.0.0.7
      And with long file names they get cut off, this sounds like it should be easy to get around, but when you are packaging large apps that have a lot of file like Perl and ISC's Bind this take a lot of leg work. I hope that helps with what I want to do here please let me know if you need any more info.
Re: Array::Compare issues
by BrowserUk (Pope) on Oct 03, 2003 at 19:50 UTC

    The output from full_compare() in a list context is a list of indices of elements that differ. To retrieve that actual values, use the returned list to index into the original arrays.

    print "line $_ differs. File 1: $file1[ $_ ] != File 2: $file2[ $_ ]\n +" for $comp->full_compare(\@file1,\@file2);

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      Great I will try that.
      Ok so we tried that and we are getting this now:
      Use of uninitialized value in concatenation (.) or string at ./compare +.pl line 25.
      Here is the updated code:
      #!/usr/bin/perl -w use Array::Compare; use strict; my $file1 = "/var/tmp/db.bind1"; my $file2 = "/var/tmp/db.bind2"; my $out = "/var/tmp/compare_out"; open(FILE1, "$file1") || die "Can't open $file1 to read\nReason: $!\n +"; my @file1 = <FILE1>; close(FILE1); open(FILE2, "$file2") || die "Can't open $file2 to read\nReason: $!\n +"; my @file2 = <FILE2>; close(FILE2); open(OUT, ">$out") || die "Cant create $out\nReason: $!\n"; my $comp = Array::Compare->new(DefFull => 1); print OUT "line $_ differs. File 1: $file1[ $_ ] != File 2: $file2[ $_ + ]\n" for $comp->full_compare(\@file1,\@file2); #$comp->compare(\@file1, \@file2); #print OUT $comp->full_compare(\@file1,\@file2); close(OUT); exit;

        That simply means that the value in one of the arrays is the null string ('') eg, a blank line.

        You can either trun of that particular warning with

        no warnings 'uninitialized';

        See perllexwarn for details.

        Or you could modify the print statement to provide better diagnostics.

        print OUT "line $_ differs. File 1: ", $file1[ $_ ] || '[blank]', " != File 2: ", $file2[ $_ ] || '[blank]', "\n" for $comp->full_compare(\@file1,\@file2);

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.

•Re: Array::Compare issues
by merlyn (Sage) on Oct 03, 2003 at 20:24 UTC
    Would a simple set difference suffice?
    @ARGV = qw(file1 file2); my %found_in; while (<>) { $found_in{$_} .= $ARGV; } print "file1 and not file2:\n"; print grep { $found_in{$_} eq "file1" }, keys %found_in; print "file2 and not file1:\n"; print grep { $found_in{$_} eq "file2" }, keys %found_in;

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Merlyn, I will take a poke at that one thanks for the advice this does seem much simpler than the method I was going about with. Thanks a million -Sunadmn
      Merlyn I have tested your sample code and I am now having an issue that I return no data. I would assume this should be returned to STDOUT but when ran like so
      [root@nscache2 tmp] 115# ./compare1.pl db.bind1 db.bind2 file1 and not file2: file2 and not file1: [root@nscache2 tmp] 116#
      I see nothing returned. Do you have any idea as to why this might be?? Here is my new code:
      #!/usr/bin/perl -w use strict; # shift(@ARGV); my %found_in; while (<>) { # $found_in{$_} .= $ARGV; $found_in{$_}{$ARGV}++; } print "file1 and not file2:\n"; print grep { $found_in{$_} eq "file1" } keys %found_in; print "file2 and not file1:\n"; print grep { $found_in{$_} eq "file2" } keys %found_in; exit;
      Thanks in advanced for any help. -Sunadmn
        Yes, my example specifically uses $ARGV, which will be sensitive to the names of the files being processed. Either rename your files to be file1 and file2, or change the strings in the two greps.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://296364]
Approved by jdtoronto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (10)
As of 2014-07-10 23:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (217 votes), past polls