Re: defined on hash value does not work in my code :(



Sorry, posted too early:-

I have corrected the error and some others, but I still have the
problem:-

Basically, the problem boils down to the following, in the code below:-

this line works:-
$times1[$#times1 + 1] = sprintf "%s",
$db{$months}{$days}{$computernames}{$hours}
if ($db{$months}{$days}{$computernames}{$hours}
&& $cts == 1);

but this one doesn't:-
$cts++ unless defined($db{$months}{$days}{$computernames}{$next})

using the debugger shows that $next has the correct value i.e. (when
$hour = 00, $next = 01) but for some reason
$db{$months}{$days}{$computernames}{$next} does not appear to ever
contain a value, even when it should!!

This is probably a silly syntax error on my part or there is something
about nested hashes that I don't understand.

Please help.

Many thanks.

=== simplified code ====

my %db;

while (<>) {
## populate %db e.g.:-
## $db{$month}{$day}{$computername}{$hour} = "$hour";
##
}

foreach my $months (sort keys %db) {
foreach my $days (sort keys %{$db{$months}}) {
foreach my $computernames (sort keys %{$db{$months}{$days}}) {
my $cts = 1; # current time slot
foreach my $hours qw/00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
15 16 17 18 19 20 21 22 23/ {
my $next = sprintf("%0.2d\n", ($hours + 1)) unless $hours eq
"23";
$times1[$#times1 + 1] = sprintf "%s",
$db{$months}{$days}{$computernames}{$hours}
if ($db{$months}{$days}{$computernames}{$hours}
&& $cts == 1);
$times2[$#times2 + 1] = sprintf "%s",
$db{$months}{$days}{$computernames}{$hours}
if ($db{$months}{$days}{$computernames}{$hours}
&& $cts == 2);
$cts++ unless
defined($db{$months}{$days}{$computernames}{$next});
}
}
}
}




Chris wrote:
> saffy wrote:
> > Apologies for posting the whole program but I can't see where I am
> > going wrong, I have tried several things to get the following line to
> > work, but it appears to be broken:-
> >
> > $cts + 1 if not
> > defined($db{$months}{$days}{$computernames}{$next});
> >
> > $cts is never incremented even if there is no defined key->value pair
> > for $db{$months}{$days}{$computernames}{$next}.
>
> That's because you're not actually incrementing $cts. Try:
>
> $cts += 1 if not defined();
>
> or
>
> ++$cts if not defined();
>
> instead.
> HTH
> Chris.
>
> >
> > I am new to perl and this is only my second program, I would appreciate
> > some advice from more experienced perl people.
> >
> > Many Thanks
> >
> >
> > ====== code follows ======
> >
> > #!/usr/bin/perl
> >
> > use strict 'vars';
> >
> > my %db;
> > my %ip2computer;
> > my %suspectipmapping;
> > my %usernamebyhour;
> > my %datesortorder = (Jan => '1', Feb => '2', Mar => '3', Apr => '4',
> > May => '5', Jun => '6', Jul => '7',
> > Aug => '8', Sep => '9', Oct => '10', Nov => '11', Dec => '12', 1 =>
> > '13', 2 => '14', 3 => '15',
> > 4 => '16', 5 => '17', 6 => '18', 7 => '19', 8 => '20', 9 => '21', 10
> > => '22', 11 => '23', 12 => '24',
> > 13 => '25', 14 => '26', 15 => '27', 16 => '28', 17 => '29', 18 =>
> > '30', 19 => '31', 20 => '32',
> > 21 => '33', 22 => '34', 23 => '35', 24 => '36', 25 => '37', 26 =>
> > '38', 27 => '39', 28 => '40',
> > 29 => '41', 30 => '42', 31 => '43', );
> >
> > sub bydate {
> > $datesortorder{$a} <=> $datesortorder{$b}
> > };
> >
> > while (<>) {
> > if (/^(\w+)\s+(\w+)\s+(\d\d):(\d\d):(\d\d)\s+.*\]\s+540\s+.*
> > User\sName:(\S+)\$.*Network\s+Address:
> >
> > (?!172\.20\.\d+\.\d+|172\.21\.20\.\d+|172\.21\.24\.\d+|127\.\d+\.\d+\.\d+)
> > (\d+\.\d+\.\d+\.\d+).*$/ix) {
> > my $month = "$1";
> > my $day = "$2";
> > my $hour = "$3";
> > my $minute = "$4";
> > my $second = "$5";
> > my $computername = uc("$6");
> > my $netaddress = "$7";
> > $db{$month}{$day}{$computername}{$hour} = "$hour"; # capture
> > hours on for computer
> > if (defined($ip2computer{$month}{$day}{$hour}{$netaddress})
> > && $ip2computer{$month}{$day}{$hour}{$netaddress} ne
> > $computername) {
> > $suspectipmapping{$ip2computer{$month}{$day}{$hour}{$netaddress}}
> > = 1;
> > $suspectipmapping{$computername} = 1;
> > }
> > else {
> > $ip2computer{$month}{$day}{$hour}{$netaddress} = $computername;
> > }
> > }
> > if (/^(\w+)\s+(\w+)\s+(\d\d):(\d\d):(\d\d)\s+.*\]\s+673\s+.*
> > User\s+Name:\s*(?!\S+\$\@)(\S+)\@.*Client\s+Address:
> >
> > (?!172\.20\.\d+\.\d+|172\.21\.20\.\d+|172\.21\.24\.\d+|127\.\d+\.\d+\.\d+)
> > (\d+\.\d+\.\d+\.\d+).*$/ix) {
> > my $month = "$1";
> > my $day = "$2";
> > my $hour = "$3";
> > my $minute = "$4";
> > my $second = "$5";
> > my $username = lc("$6");
> > my $netaddress = "$7";
> > unless
> > ($usernamebyhour{$month}{$day}{$hour}{$ip2computer{$month}{$day}{$hour}{$netaddress}}
> > =~ /($username)/i) {
> >
> > $usernamebyhour{$month}{$day}{$hour}{$ip2computer{$month}{$day}{$hour}{$netaddress}}
> > .= "$username "
> > }
> > }
> > }
> >
> > #print "Report for domain PCs that communicated with domain
> > controllers, along with
> > #users who logged onto those PCs at least once.\n\n";
> >
> > foreach my $months (sort bydate keys %db) {
> > foreach my $days (sort bydate keys %{$db{$months}}) {
> > #print "\n$months $days\n";
> > foreach my $computernames (sort keys %{$db{$months}{$days}}) {
> > printf "%s,%s,%s,", ($months,$days,$computernames);
> > my @times1;
> > my @times2;
> > my @times3;
> > my @times4;
> > my @users;
> > foreach my $hours qw/00 01 02 03 04 05 06 07 08 09 10 11 12
> > 13 14 15 16 17 18 19 20 21 22 23/ {
> > my $previous = sprintf("%0.2d\n", ($hours - 1)) unless
> > $hours eq "00";
> > my $next = sprintf("%0.2d\n", ($hours + 1)) unless
> > $hours eq "23";
> > my $cts = 1; # current time slot
> > @times1[$#times1 + 1] = sprintf "%s",
> > $db{$months}{$days}{$computernames}{$hours}
> > if ($db{$months}{$days}{$computernames}{$hours}
> > && $cts == 1);
> > @times2[$#times2 + 1] = sprintf "%s",
> > $db{$months}{$days}{$computernames}{$hours}
> > if ($db{$months}{$days}{$computernames}{$hours}
> > && $cts == 2);
> > @times3[$#times3 + 1] = sprintf "%s",
> > $db{$months}{$days}{$computernames}{$hours}
> > if ($db{$months}{$days}{$computernames}{$hours}
> > && $cts == 3);
> > @times4[$#times4 + 1] = sprintf "%s",
> > $db{$months}{$days}{$computernames}{$hours}
> > if ($db{$months}{$days}{$computernames}{$hours}
> > && $cts == 4);
> >
> > ### The following line does not appear to work
> > $cts + 1 if not
> > defined($db{$months}{$days}{$computernames}{$next});
> > @users[$#users + 1] = sprintf "%s",
> > $usernamebyhour{$months}{$days}{$hours}{$computernames}
> > if
> > $usernamebyhour{$months}{$days}{$hours}{$computernames};
> > };
> > printf "%s,%s,", @times1[0,$#times1];
> > printf "%s,%s,", @times2[0,$#times2];
> > printf "%s,%s,", @times3[0,$#times3];
> > printf "%s,%s,", @times4[0,$#times4];
> > chop @users;
> > printf "%s,%s", @users[0,$#users];
> > print "\n";
> > }
> > #print "\nDaily total number of PCs: " .
> > keys(%{$db{$months}{$days}}) . "\n";
> > }
> > }
> >

.