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

Hello Monks,

I'm having a problem with the below code. When I run this code with strict enabled, I get the following error:
:!./temp site Can't use string ("ftp.siebel.com") as a HASH ref while "strict refs" in use at ./temp line 51. shell returned 255
if I disable strict, I get:
site Use of uninitialized value in concatenation (.) or string at ./temp line 51. site -> Use of uninitialized value in concatenation (.) or string at ./temp line 52. site -> ftp.siebel.com ftp.siebel.com -> 64.181.143.36 ftp.siebel.com -> 64.181.143.36 ebusiness.siebel.com ebusiness.siebel.com -> 64.181.189.50 ebusiness.siebel.com -> 64.181.189.50 www.siebel.com www.siebel.com -> 64.181.189.55 www.siebel.com -> 64.181.189.55 messenger.hotmail.com messenger.hotmail.com -> 207.46.104.20 messenger.hotmail.com -> 207.46.104.20
I can't figure out why I'm getting an empty entry. Hashes always seem to drive me bonkers, but I think it's the best data structure to use in this scenario. I would appreciate any help.
1 #!/usr/bin/perl -w 2 # 3 # lookup.pl - Check if these sites have changed their ip address 4 # 5 6 #use strict; 7 use Net::Nslookup; 8 use Mail::Sender; 9 10 my %hash; 11 12 # MSN Messenger 13 my $msndns = 'messenger.hotmail.com'; 14 my $msnip = '207.46.104.20'; 15 my $msn = nslookup(host => "$msndns", type => "A"); 16 17 $hash{site} = $msndns; 18 $hash{$msndns}{ip_now} = $msnip; 19 $hash{$msndns}{ip_new} = $msn; 20 21 # www.siebel.com 22 my $www_siebel_dns = 'www.siebel.com'; 23 my $www_siebel_ip = '64.181.189.55'; 24 my $www_siebel = nslookup(host => "$www_siebel_dns", type => "A"); 25 26 $hash{site} = $www_siebel_dns; 27 $hash{$www_siebel_dns}{ip_now} = $www_siebel_ip; 28 $hash{$www_siebel_dns}{ip_new} = $www_siebel; 29 30 # ebusiness.siebel.com 31 my $ebiz_siebel_dns = 'ebusiness.siebel.com'; 32 my $ebiz_siebel_ip = '64.181.189.50'; 33 my $ebiz_siebel = nslookup(host => "$ebiz_siebel_dns", type => "A" +); 34 35 $hash{site} = $ebiz_siebel_dns; 36 $hash{$ebiz_siebel_dns}{ip_now} = $ebiz_siebel_ip; 37 $hash{$ebiz_siebel_dns}{ip_new} = $ebiz_siebel; 38 39 # ftp.siebel.com 40 my $ftp_siebel_dns = 'ftp.siebel.com'; 41 my $ftp_siebel_ip = '64.181.143.36'; 42 my $ftp_siebel = nslookup(host => "$ftp_siebel_dns", type => "A"); 43 44 $hash{site} = $ftp_siebel_dns; 45 $hash{$ftp_siebel_dns}{ip_now} = $ftp_siebel_ip; 46 $hash{$ftp_siebel_dns}{ip_new} = $ftp_siebel; 47 48 49 for my $j ( keys(%hash) ){ 50 print "$j\n"; 51 print "$j -> $hash{$j}{ip_now}\n"; 52 print "$j -> $hash{$j}{ip_new}\n"; 53 }

Replies are listed 'Best First'.
Re: Problem with Hash when Using Strict
by bobf (Monsignor) on Sep 17, 2004 at 19:24 UTC

    The previous two posts explain why you're getting the error. If you want to keep the 'site' key in the hash for whatever reason (even though it seems redundant), you can simply add another layer so it follows the HoH structure of the other data. That way all of the keys in %hash are hashrefs:

    $hash{$ebiz_siebel_dns}{site} = $ebiz_siebel_dns; $hash{$ebiz_siebel_dns}{ip_now} = $ebiz_siebel_ip; $hash{$ebiz_siebel_dns}{ip_new} = $ebiz_siebel; for my $j ( keys(%hash) ){ print "site -> $j\n"; # $j eq $hash{$j}{site} print "$j -> $hash{$j}{ip_now}\n"; print "$j -> $hash{$j}{ip_new}\n"; }

    It also seems that you are creating a lot of unnecessary variables (three for each site). You might want to consider restructuring this block something like this:

    my %sites = ( 'messenger.hotmail.com' => { ipnow => '207.46.104.20', type => 'A' }, 'www.siebel.com' => { ipnow => '64.181.189.55', type => 'A' }, ); foreach my $dns ( keys %sites ) { $sites{$dns}{ipnew} = nslookup( host => $dns, type => $sites{$dns}{type} ); } foreach my $dns ( keys %sites ) { print "$dns\n"; print "$dns -> $sites{$dns}{ipnow}\n"; print "$dns -> $sites{$dns}{ipnew}\n"; }

    This way, if you want to add (or remove) a site from the list, you simply edit the %sites hash and leave the rest of the code alone. It also keeps all of the nslookup calls together, and (IMO) it makes it easier to follow the code.

    HTH

Re: Problem with Hash when Using Strict
by shenme (Priest) on Sep 17, 2004 at 18:02 UTC
    You are putting two different kinds of data into %hash. See line
    44 $hash{site} = $ftp_siebel_dns;
    This is a string and not a hash reference. Probably this line is left-over from earlier testing?
Re: Problem with Hash when Using Strict
by Eimi Metamorphoumai (Deacon) on Sep 17, 2004 at 18:03 UTC
    The problem is that you keep assigning to $hash{site}, so when you look at the keys for %hash, one of them is "site". As far as I can tell, there's no reason for the assignment to $hash{site} in the first place.
Re: Problem with Hash when Using Strict
by Lhamo Latso (Scribe) on Sep 17, 2004 at 19:25 UTC

    There are a few problems here. You are using %hash for 2 different things: a hash with key=site, value=ftp.siebel.com; a hashref with key={ftp.siebel.com}{ip_now} = 64.181.143.36 and {ip_new} = something other ip address.

    Your loop structure complains that the hashref is missing when the key=site. Adding the following would get rid of the error, but only by filling in the void after line 39 above:

    $hash{site} = $ftp_siebel_dns; $hash{site}{ip_now} = "x"; $hash{site}{ip_new} = "y";

    A better way would be to change the structure to:

    %HoH = ( $ftp_siebel_dns => { ip_now => $ftp_siebel_ip, ip_new => $ftp_siebel, }, );

    That looks about the same, but you would not have any key called site.

      $hash{site} = $ftp_siebel_dns; $hash{site}{ip_now} = "x"; $hash{site}{ip_new} = "y";
      That won't work for the same reason the OP's code doesn't work--you're making $hash{site} both a string and a hashref. The other suggestion is good, though.