Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Compare two hash values for a match

by vlad3848 (Acolyte)
on Oct 13, 2013 at 07:47 UTC ( #1058044=perlquestion: print w/replies, xml ) Need Help??
vlad3848 has asked for the wisdom of the Perl Monks concerning the following question:

Hi All! I am trying to compare a value in hash #1 against the value of hash #2. If there is a match (oids match), I'd want to print the key of hash #2 (the device name).

However, I am currently dealing with two issues:

1)One of the hash values always comes back undef.

2)Here are the errors i get:

Use of uninitialized value in string eq at hostdb.pl line 24, <FILE> l +ine 7. Device missing field 'sysoid'.

(I am assuming these errors are result of "undef" value in one of the hashes)

How can i compare two of these hash values to each other?

Here is how i create my hashes:

#! /usr/bin/perl use warnings; use strict; use Sys::Hostname; use DBI; use Data::Dumper; open OUTPUT, ">", "output.txt"; my ($source, %current, @stuff, %lookup, $nodelabel,$name, $key,%revers +e); $source= "source"; &dbConnect; &getHosts; &lookup; my @keys = keys %lookup; my @key2 = keys %current; print Dumper $lookup{$name}{"sysoid"}; foreach $key(@key2){ if($current{$key}{"nodesysoid"} eq "" || $lookup{$name}{"sysoid"} eq " +"){ if($current{$key}{"nodesysoid"} eq ""){ print "Device missing field 'nodesysoid'.\n"; } if ($lookup{$name}{"sysoid"} eq ""){ print "Device missing field 'sysoid'.\n"; }else{ print "everythin looks ok\n"; } } } sub dbConnect { # database connection variables my $dbPort = "5432"; my $dbPass = "password"; my $dbUser = "username"; my $dbName = "dbname"; # Get the database hostname my $dbHost; my $dbh = DBI->connect("DBI:Pg:dbname=$dbName; host=localhost; por +t=$dbPort", $dbUser, $dbPass, {AutoCommit => 0, RaiseError => 1, PrintError +=> 0} ); return ($dbh,$dbHost); } sub getHosts { # connect to the database my ($dbh,$dbHost) = dbConnect(); # prepare and execute the query my $sth = $dbh->prepare("SELECT distinct node.nodelabel, node.node +sysoid, ipinterface.ipaddr FROM node left JOIN ipinterface on ipinte +rface.nodeid=node.nodeid WHERE node.nodesysoid is not NULL AND ipi +nterface.issnmpprimary = 'P';"); $sth->execute; # Turn the query into a hash reference and save the data while (my $results = $sth->fetchrow_hashref) { # save the data for our own using. my $nodelabel = lc($results->{nodelabel}); # lowercase this na +me too my $ipaddr = $results->{ipaddr}; my $sysoid = $results->{nodesysoid}; $current{$nodelabel}{"nodelabel"} = $nodelabel; $current{$nodelabel}{"ipaddr"} = $ipaddr; $current{$nodelabel}{"nodesysoid"} = $sysoid; print OUTPUT $current{$nodelabel}{"nodelabel"} . ",". $current +{$nodelabel}{"nodesysoid"} .",".$current{$nodelabel}{"ipaddr"}. "," . + $source . "\n"; } # disconnect from the database $dbh->disconnect(); } sub lookup { open FILE, "<lookup.txt" or die $!; while (<FILE>) { chomp; my ($name, $sysoid) = split(/,/,$_); if ((not defined $name) || (not defined $sysoid)) { next; }else { $lookup{$name}{"name"}=$name; $lookup{$name}{"sysoid"}=$sysoid; } } }

Here is how my fist hash looks like:

'host1.yourdomain.com' => { 'nodelabel' => ''host1. +yourdomain.com'', 'nodesysoid' => '.1.3.6 +.1.4.1.9.1.748', 'ipaddr' => '159.140.67 +.253' }, 'host2.yourdomain.com' => { 'nodelabel' => ''host2. +yourdomain.com'', 'nodesysoid' => '.1.3.6 +.1.4.1.9.1.1144', 'ipaddr' => '159.140.67 +.254' }, 'host3.yourdomain.com' => { 'nodelabel' => ''host3.y +ourdomain.com'', 'nodesysoid' => '.1.3.6. +1.4.1.9.1.223', 'ipaddr' => '159.140.67. +252' }, 'host4.yourdomain.com' => { 'nodelabel' => 'host4. +yourdomain.com', 'nodesysoid' => '.1.3. +6.1.4.1.9.1.748',

Here is how my second hash looks like:

$VAR1 = { 'C2900' => { 'sysoid' => '.1.3.6.1.4.1.9.1.1045', 'name' => 'C2900' }, 'ASR1001' => { 'sysoid' => '.1.3.6.1.4.1.9.1.1165', 'name' => 'ASR1001' }, 'ASR1002' => { 'sysoid' => '.1.3.6.1.4.1.9.1.923', 'name' => 'ASR1002' }, '3925-SPE200' => { 'sysoid' => '.1.3.6.1.4.1.9.1.1144', 'name' => '3925-SPE200' }, 'ACE10-6500-K9' => { 'sysoid' => '.1.3.6.1.4.1.9.1.730', 'name' => 'ACE10-6500-K9' }, '7204VXR' => { 'sysoid' => '.1.3.6.1.4.1.9.1.223', 'name' => '7204VXR' }, '7206VXR' => { 'sysoid' => '.1.3.6.1.4.1.9.1.222', 'name' => '7206VXR' } };

Here is what lookup file looks like:

7204VXR,.1.3.6.1.4.1.9.1.223, ASR1001,.1.3.6.1.4.1.9.1.1165, ASR1002,.1.3.6.1.4.1.9.1.923, 7206VXR,.1.3.6.1.4.1.9.1.222, C2900,.1.3.6.1.4.1.9.1.1045, 3925-SPE200,.1.3.6.1.4.1.9.1.1144, ACE10-6500-K9,.1.3.6.1.4.1.9.1.730,

If i just print print Dumper $lookup{$name}{"sysoid"}; I get the following

Use of uninitialized value in hash element at hostdb.pl line 17, <FILE +> line 7. $VAR1 = undef;

Replies are listed 'Best First'.
Re: Compare two hash values for a match
by LanX (Bishop) on Oct 13, 2013 at 09:26 UTC
    in your top scope '$name' is never set, i.e. it's undef in all your attempts as hash key.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      Thank you! That made a lot of sense! Since it was not getting defined i couldn't compare my keys to undefined value. I changed it to
      foreach $key(@key2) { $sysdef = $current{$key}{"nodesysoid"}; if (exists $lookup{$sysdef}){ #print "$key, $sysdef, $lookup{$sysdef}{name}, $source\n"; } }
Re: Compare two hash values for a match
by hdb (Monsignor) on Oct 13, 2013 at 09:52 UTC

    It seems much easier to me to set up your lookup like this

    $lookup{$sysoid} = $name;
    instead of
    $lookup{$name}{"name"}=$name; $lookup{$name}{"sysoid"}=$sysoid;
    because that is how you want to use it.
      Thank you! I actually reversed it and made my sysoid as the key value. It made it easier to compare keys later
      if (defined $name and defined $sysoid){ $lookup{$sysoid}{name} = $name; } }
Re: Compare two hash values for a match
by builat (Monk) on Oct 13, 2013 at 08:38 UTC
    Why you do not use?
    unless ((defined $name) or (defined $sysoid)){..}

      I agree, the logic can be usefully simplified here. But your suggested change is not correct. With the negations unwound, the equivalent logic is:

      if (defined $name and defined $sysoid) { $lookup{$name}{name} = $name; $lookup{$name}{sysoid} = $sysoid; }

      (But I would normally use the higher-precedence && in this situation in preference to the lower-precedence and, which I tend to reserve for control flow.)

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Yes. Right. My mistake. Shame on me.
Re: Compare two hash values for a match
by Laurent_R (Canon) on Oct 13, 2013 at 09:15 UTC

    Difficult to say because I can't test your program (not having the DB), but probably $name is not defined when you dump $lookup{$name}{"sysoid"}, you should test it before dumping it. Similarly, these tests:

    if($current{$key}{"nodesysoid"} eq "" || $lookup{$name}{"sysoid"} eq " +"){ if($current{$key}{"nodesysoid"} eq ""){ # ...

    should probably be protected against non existing and/or undefined values (unless you can be sure that this is never going to happen).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1058044]
Approved by Happy-the-monk
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2018-07-16 23:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (352 votes). Check out past polls.

    Notices?