duck has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to read in two files and store the contents into hashes. Then compare the contents to see if the versions number are the same if the package exists in both files. INPUT FILE 1:
CSWcommon,1.4.5 CSWexpat,1.95.7 CSWggettext,"0.14.1,REV=2005.06.29" CSWgmake,3.81
INPUT FILE 2:
CSWcommon,1.4.5 CSWexpat,1.95.7 CSWggettext,"0.14.1,REV=2005.06.29" CSWgmake,3.81
CODE:
#!/usr/bin/perl # ## Define variables # $EMPTY=""; # ## Open file 1 for input and place contents into hash table # $FILENAME1 = shift; open(FILE1,"./$FILENAME1") || die "USEAGE ./checker file1 file2\n"; while(<FILE1>){ @PACKAGE1 = split(',',$_,2); $FILE1PKG{$PACKAGE1[0]}{$PACKAGE1[1]} = $_; #%FILE1PKG=($PACKAGE1[0]=>{Version=>$PACKAGE1[1]} ); } close FILE1; # ## Open file 2 and compare the two this will create several outputs # $FILENAME2 = shift; open(FILE2,"./$FILENAME2") || die "USEAGE ./checker file1 file2\n"; while(<FILE2>){ @PACKAGE2 = split(',',$_,2); $FILE2PKG{$PACKAGE2[0]}{$PACKAGE2[1]} = $_; } close FILE2; for $MASTERPKG ( keys %FILE1PKG ){ print "FILE1 PACKAGE: $MASTERPKG VERSION: ",(keys %{ $FILE1PKG{$ +MASTERPKG}}); $VERSION1 = $FILE1PKG{$MASTERPKG}; $VERSION2 = $FILE2PKG{$MASTERPKG}; print "VERSION1: $VERSION1 VERSION2: $VERSION2\n"; print "FILE2 PACKAGE: $MASTERPKG VERSION: ",(keys %{ $FILE2PKG{$ +MASTERPKG}}); if ($VERSION1 eq $VERSION2) {print "SAME\n"}; }
OUTPUT:
FILE1 PACKAGE: SUNWkmp2r VERSION: "5.0,REV=2001.10.01.15.47" VERSION1: HASH(0x93f5458) VERSION2: HASH(0x945a948) FILE2 PACKAGE: SUNWkmp2r VERSION: "5.0,REV=2001.10.01.15.47"
I am fairly new to using perl and most of the answers I have seen to simular issues are complete greek to me. Thank you Duck

Replies are listed 'Best First'.
Re: Hash comparing
by jethro (Monsignor) on Nov 05, 2008 at 20:38 UTC

    You store the version of each package as a key of a subhash. That would only make sense if you expected more than one version of a package to be in one file or need to store other info into that hash as well.

    I can give you the line to make your equality test workable, but that will not fix the issue that you used (IMHO) the wrong data structure:

    if ( (keys %$VERSION1)[0] eq (keys %$VERSION2)[0]) {print "SAME\n"};

    Much better would be to just store the version in the hash like this: $FILE1PKG{$PACKAGE1[0]}= $PACKAGE1[1];. Note that you can get the whole line anytime by simply concatenating key and value of your hash. Then your old equality line would work

      Thank you!
      Sorry if it looks like I am shouting this is the way I have always done my variables. At least for me they are easier to spot.
      I was using code from a previous script and was not entirely sure what it was doing.

      $FILE1PKG{$PACKAGE1[0]}{$PACKAGE1$FILE1PKG[1]} = $_;

      Changed to
      $FILE1PKG{$PACKAGE1[0]}=$PACKAGE1[1];


      Also thank you for keeping it simple! I now have most things working and understand my errors much better!

      As for the output being different I just used the first few lines of input and after posting realized I forgot to limit this for testing.


      #!/usr/bin/perl # ## Define variables # $EMPTY=""; # ## Open file 1 for input and place contents into hash table # $FILENAME1 = shift; open(FILE1,"./$FILENAME1") || die "USEAGE ./checker file1 file2\n"; while(<FILE1>){ @PACKAGE1 = split(',',$_,2); #$FILE1PKG{$PACKAGE1[0]}{$PACKAGE1[1]} = $_; $FILE1PKG{$PACKAGE1[0]}=$PACKAGE1[1]; } close FILE1; # ## Open file 2 and compare the two this will create several outputs # $FILENAME2 = shift; open(FILE2,"./$FILENAME2") || die "USEAGE ./checker file1 file2\n"; while(<FILE2>){ @PACKAGE2 = split(',',$_,2); $FILE2PKG{$PACKAGE2[0]}=$PACKAGE2[1]; } close FILE2; # ## Read in hash and do comparisons # for $MASTERPKG ( keys %FILE1PKG ){ print "FILE1 PACKAGE: $MASTERPKG VERSION: ",$FILE1PKG{$MASTERPKG +}; print "FILE2 PACKAGE: $MASTERPKG VERSION: ",$FILE2PKG{$MASTERPKG +}; $VERSION1 = $FILE1PKG{$MASTERPKG}; $VERSION2 = $FILE2PKG{$MASTERPKG}; #print "\nVERSION1: $VERSION1 VERSION2: $VERSION2\n"; if ($VERSION1 eq $VERSION2) {print "SAME\n"}; if ($VERSION2 eq $EMPTY) {print "MISSING PACKAGE\n"}; if (($VERSION1 ne $VERSION2) && ($VERSION2 ne $EMPTY)) {print "DIFFER +ENT\n"}; }


      All seems to be working as expected!

      I also use caps when testing again I find it makes the output I am looking for stand out more

      All who have responded thank you for your time and efforts!
      Duck
Re: Hash comparing
by JadeNB (Chaplain) on Nov 05, 2008 at 20:26 UTC
    There doesn't seem to be a question here, so I'll guess. I think that you probably want your assignment line to be
    $FILE1PKG{$PACKAGE1[0]} = $PACKAGE1[1];
    (and similarly for $FILE2PKG). As it stands, every value of %FILE1PKG is a reference to an entire (albeit 1-key) hash, and it's those hashrefs that you're trying to compare.

    Further, notice that the last argument, 2, on your splits is saying not to grab more than 2 fields. That's why the REV is trailing along with the VERSION. If you want to discard everything but the first two fields, then you can do something like my ( $key, $value ) = split(',', $_);.

    There are other issues, like the absence of use strict; use warnings; and the non-declaration of various variables, but I think those are the ones that are affecting your functionality.

    Also, did you really want to use a string-comparison eq?

    UPDATE: On further reading, your OUTPUT does not come from the INPUT you provided. Also, I've stricken the comment about split because I guess from your example data that you want to carry the REV data inside the VERSION. Notice, though, that this looks like CSV, so you should be parsing it with something like Text::CSV, not hand-rolling.

Re: Hash comparing
by jwkrahn (Abbot) on Nov 05, 2008 at 20:21 UTC

    Why is your code  SHOUTING at me?   It hurts my head!

      10 PRINT "TAKE A BREAK! EAT A CAKE!" 20 GOTO 10 RUN

        Oh, if only I had a cake I would eat it, but alas, I am cakeless.