For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > March 2004 > Hash Help Needed !









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Hash Help Needed !
Jason Normandin

2004-03-26, 11:14 pm

Hey List.

I have run into a situation that I am unclear on.

I am making the following assignment during a loop:

push @{$response_hash{$request_id}},{time => "$time",ip_addr => "$ip_address",oids => "%response_values"};

Where: response_values is a simple hash containing key,value pairs and $time and $ip_address are simple scalar vars.

I can iterate through the %response_values hash after it is created localy using simple foreach my $value (keys %response_values ) syntax, but when I try to include that iteration when iterating the main response hash, I am not getting any values.

I am using the following syntax:

foreach my $request (sort keys %response_hash) {
print "Response to request_id $request\n";
foreach my $record(@{$response_hash{$request}}) {

print "Time : $record->{time}\n";
print "IP : $record->{ip_addr}\n";
foreach my $response ($record->{keys %response_values} )
{
print "Response to oid : $response = $response_values{$response}\n";
}
}

}

The other attributes of the %response_hash are printing fine, just not the contents of the %response_values hash.

I have also tried assigning as a referance, but that does not seem to work either:

push @{$response_hash{$request_id}},{time => "$time",ip_addr => "$ip_address",oids => "\%response_values"};

I get an error when trying to referance it later during the main hash iteration:

Type of arg 1 to keys must be hash (not reference constructor) at H:\nhsParseSnmpLog.pl line 56, near "%response_values}
"

I am pretty at this point and would really appreciate any help I could get.

Thanks!!
Jason

Charles K. Clarkson

2004-03-26, 11:14 pm

jason_normandin@charter.net <jason_normandin@charter.net> wrote:
:
: I have run into a situation that I am unclear on.
:
: I am making the following assignment during a loop:
:
: push @{$response_hash{$request_id}},{time => "$time",ip_addr
: => "$ip_address",oids => "%response_values"};

I didn't test your code but "%response_values" is not the
same as \%response_values or %response_values. You have just
run into the problem with unnecessarily quoting variables.
(Read perlfaq4.)

You might have wanted (White space is your friend.):

push @{ $response_hash{ $request_id } }, {
time => $time,
ip_addr => $ip_address,
oids => \%response_values,
};



:
: Where: response_values is a simple hash containing key,value
: pairs and $time and $ip_address are simple scalar vars.
:
: I can iterate through the %response_values hash after it is
: created localy using simple foreach my $value (keys
: %response_values ) syntax, but when I try to include that
: iteration when iterating the main response hash, I am not
: getting any values.
:
: I am using the following syntax:

Add this near the top of your script. It adds a function
named Dumper to your script.

use Data::Dumper 'Dumper';

:
: foreach my $request (sort keys %response_hash) {
: print "Response to request_id $request\n";
: foreach my $record(@{$response_hash{$request}}) {

Test what is in $record with the Dumper function:

print Dumper @record;
exit;

Is the result what you thought was in there?


:
: print "Time : $record->{time}\n";
: print "IP : $record->{ip_addr}\n";
: foreach my $response ($record->{keys %response_values} )
: {
: print "Response to oid : $response =
: $response_values{$response}\n";
: }
: }
:
: }

HTH,

Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328


Wiggins D Anconia

2004-03-26, 11:14 pm

> jason_normandin@charter.net <jason_normandin@charter.net> wrote:

[snip]

> :
> : print "Time : $record->{time}\n";
> : print "IP : $record->{ip_addr}\n";
> : foreach my $response ($record->{keys %response_values} )


In addition to what Charles already stated, once you have cleared up the
quoting problem and gotten your hash to store properly, then you will
need to access the hash reference of the key in the main hash using
'oids' . In other words, you need to index into $record using 'oids' to
get the hash reference, then take the keys of that dereferenced hash.

foreach my $response (keys %{ $record->{'oids'} }) {

I suspect you have a scoping issue with %response_values otherwise
strict would have complained, are you declaring your variables when
first used or all at the top? %response_values should have been a
temporary variable scoped only to your first loop which you didn't show.

http://danconia.org
Jason Normandin

2004-03-26, 11:14 pm

Got it. I missed your note on the whitespace.

Thanks everyone !!

>
> From: "Charles K. Clarkson" <cclarkson@htcomp.net>
> Date: 2004/03/25 Thu PM 03:35:08 GMT
> To: <jason_normandin@charter.net>, <beginners@perl.org>
> CC: <jnormandin@concord.com>
> Subject: RE: Hash Help Needed !
>
> jason_normandin@charter.net <jason_normandin@charter.net> wrote:
> :
> : I have run into a situation that I am unclear on.
> :
> : I am making the following assignment during a loop:
> :
> : push @{$response_hash{$request_id}},{time => "$time",ip_addr
> : => "$ip_address",oids => "%response_values"};
>
> I didn't test your code but "%response_values" is not the
> same as \%response_values or %response_values. You have just
> run into the problem with unnecessarily quoting variables.
> (Read perlfaq4.)
>
> You might have wanted (White space is your friend.):
>
> push @{ $response_hash{ $request_id } }, {
> time => $time,
> ip_addr => $ip_address,
> oids => \%response_values,
> };
>
>
>
> :
> : Where: response_values is a simple hash containing key,value
> : pairs and $time and $ip_address are simple scalar vars.
> :
> : I can iterate through the %response_values hash after it is
> : created localy using simple foreach my $value (keys
> : %response_values ) syntax, but when I try to include that
> : iteration when iterating the main response hash, I am not
> : getting any values.
> :
> : I am using the following syntax:
>
> Add this near the top of your script. It adds a function
> named Dumper to your script.
>
> use Data::Dumper 'Dumper';
>
> :
> : foreach my $request (sort keys %response_hash) {
> : print "Response to request_id $request\n";
> : foreach my $record(@{$response_hash{$request}}) {
>
> Test what is in $record with the Dumper function:
>
> print Dumper @record;
> exit;
>
> Is the result what you thought was in there?
>
>
> :
> : print "Time : $record->{time}\n";
> : print "IP : $record->{ip_addr}\n";
> : foreach my $response ($record->{keys %response_values} )
> : {
> : print "Response to oid : $response =
> : $response_values{$response}\n";
> : }
> : }
> :
> : }
>
> HTH,
>
> Charles K. Clarkson
> --
> Mobile Homes Specialist
> 254 968-8328
>
>
>
> --
> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
> For additional commands, e-mail: beginners-help@perl.org
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>
>


Wiggins D Anconia

2004-03-26, 11:14 pm

Please bottom post....

> Hi
>
> I am scoping the %response_values hash at the top. I dont understand

why it
> would need to be temporary as I am referancing that hash outside of

the loop
> when I iterate through.
>


It doesn't have to be temporary, but you overstep the help that 'strict'
would have given you in finding at least one of your problems. By
declaring it outside of the scope necessary, it is available later on in
your block when it likely doesn't need to be.

> I changed the syntax to referance the oids rather then the hash name and I
> get the following error:
>
> Can't use string ("%response_values") as a HASH ref while "strict refs" in
> use at H:\nhsParseSnmpLog.pl line 72, <SNMP_L
> OG> chunk 78.
>


Exactly. That is what you want to see, because this is telling you that
you are trying to use a string as a hash reference, which should tell
you that you don't have the structure you want. In other words, this
just told you that you shouldn't have quoted %response_values to begin with.

> Here is what I have:
>
> .. SNIP..
> use strict;
> my (%request_hash,%response_hash);
>
> .. SNIP...
> elsif ( m/RESPONSE:/ ) {
> my
>

($time,$timeSecs,$request_id,$ip_address
,%response_values,$oid,$oid_value);[colo
r=darkred]
> # Set these local to each record[/color]

Which is exactly what you haven't done, aka they are local to the
enclosing 'if' block, not the foreach. If you scope them inside of the
foreach, which should be sufficient from what you have shown us, then
'strict' will also complain later about using %response_values.

> my @lines = split/\n/;
> foreach my $line (@lines) {
> next if $line =~ m/REQUEST:/;
> $timeSecs=$1 if $line =~ m/# Time (\d+)\.\d+
> seconds/;
> $time=convertUtcToLocaltime($timeSecs
);
> $request_id=$1 if $line =~ m/\[REQUEST_ID\] (\d+)/;
> $oid=$1 if $line =~ m/\[OBJECT_ID \] (.+)/;
> $oid_value =$1 if $line =~ m/[\[COUNTER \]|\[GAUGE
> \]|\[INT \]|\[TICKS \]] (.+)/;
> $response_values{$oid}=$oid_value;
> }
> push @{$response_hash{$request_id}},{time => "$time",oids =>
> "%response_values"};


Right here the values you push can go out of scope because they will
still exist referenced inside of 'response_hash'.

> }
>
> .. SNIP ..
>
> foreach my $request (sort keys %response_hash) {
> #print "Response to request_id $request\n";
> foreach my $record(@{$response_hash{$request}}) {
> #print "Time : $record->{time}\n";
> foreach my $response (keys %{ $record->{'oids'} }) {
> #foreach my $response ($record->{keys %response_values} )
>
> print "Response to oid : $response =
> $record->{'oids'}{$response}\n";
> }
> }
> #print "============================\n";
> }
>
> I am thoroughly at this point :(
>


That's fine, references are generally pretty difficult to "get" but once
you have gotten them you will have plenty of doors opened to you. You
may want to read, if you haven't already:

perldoc perldsc
perldoc perllol
perldoc perlreftut
perldoc perlref

Come back when/if you have more questions,

http://danconia.org

[snip old posts]
Jason Normandin

2004-03-26, 11:14 pm

Charles

It does not print anything even though I know the time and ip_address
objects are populated as they print correctley.

I added the following ( and use Data::Dumper 'Dumper'; to the top of the
script )

foreach my $request (sort keys %response_hash) {
#print "Response to request_id $request\n";
foreach my $record(@{$response_hash{$request}}) {
print Dumper @record;
#print "Time : $record->{time}\n";
foreach my $response ($record->{keys %response_values} )
{
#print "Response to oid : $response =
$response_values{$response}\n";
}
}

What am I missing here ?

Thanks !

-----Original Message-----
From: Charles K. Clarkson [mailto:cclarkson@htcomp.net]
Sent: Thursday, March 25, 2004 10:35 AM
To: jason_normandin@charter.net; beginners@perl.org
Cc: Normandin, Jason
Subject: RE: Hash Help Needed !


jason_normandin@charter.net <jason_normandin@charter.net> wrote:
:
: I have run into a situation that I am unclear on.
:
: I am making the following assignment during a loop:
:
: push @{$response_hash{$request_id}},{time => "$time",ip_addr
: => "$ip_address",oids => "%response_values"};

I didn't test your code but "%response_values" is not the
same as \%response_values or %response_values. You have just
run into the problem with unnecessarily quoting variables.
(Read perlfaq4.)

You might have wanted (White space is your friend.):

push @{ $response_hash{ $request_id } }, {
time => $time,
ip_addr => $ip_address,
oids => \%response_values,
};



:
: Where: response_values is a simple hash containing key,value
: pairs and $time and $ip_address are simple scalar vars.
:
: I can iterate through the %response_values hash after it is
: created localy using simple foreach my $value (keys
: %response_values ) syntax, but when I try to include that
: iteration when iterating the main response hash, I am not
: getting any values.
:
: I am using the following syntax:

Add this near the top of your script. It adds a function
named Dumper to your script.

use Data::Dumper 'Dumper';

:
: foreach my $request (sort keys %response_hash) {
: print "Response to request_id $request\n";
: foreach my $record(@{$response_hash{$request}}) {

Test what is in $record with the Dumper function:

print Dumper @record;
exit;

Is the result what you thought was in there?


:
: print "Time : $record->{time}\n";
: print "IP : $record->{ip_addr}\n";
: foreach my $response ($record->{keys %response_values} )
: {
: print "Response to oid : $response =
: $response_values{$response}\n";
: }
: }
:
: }

HTH,

Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328



****************************************
******************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.
This footnote also confirms that this email message has been swept by
the latest virus scan software available for the presence of computer
viruses.
****************************************
******************************


Jason Normandin

2004-03-26, 11:14 pm

Hi

I am scoping the %response_values hash at the top. I dont understand why it
would need to be temporary as I am referancing that hash outside of the loop
when I iterate through.

I changed the syntax to referance the oids rather then the hash name and I
get the following error:

Can't use string ("%response_values") as a HASH ref while "strict refs" in
use at H:\nhsParseSnmpLog.pl line 72, <SNMP_L
OG> chunk 78.

Here is what I have:

... SNIP..
use strict;
my (%request_hash,%response_hash);

... SNIP...
elsif ( m/RESPONSE:/ ) {
my
($time,$timeSecs,$request_id,$ip_address
,%response_values,$oid,$oid_value);
# Set these local to each record
my @lines = split/\n/;
foreach my $line (@lines) {
next if $line =~ m/REQUEST:/;
$timeSecs=$1 if $line =~ m/# Time (\d+)\.\d+
seconds/;
$time=convertUtcToLocaltime($timeSecs);
$request_id=$1 if $line =~ m/\[REQUEST_ID\] (\d+)/;
$oid=$1 if $line =~ m/\[OBJECT_ID \] (.+)/;
$oid_value =$1 if $line =~ m/[\[COUNTER \]|\[GAUGE
\]|\[INT \]|\[TICKS \]] (.+)/;
$response_values{$oid}=$oid_value;
}
push @{$response_hash{$request_id}},{time => "$time",oids =>
"%response_values"};
}

... SNIP ..

foreach my $request (sort keys %response_hash) {
#print "Response to request_id $request\n";
foreach my $record(@{$response_hash{$request}}) {
#print "Time : $record->{time}\n";
foreach my $response (keys %{ $record->{'oids'} }) {
#foreach my $response ($record->{keys %response_values} )

print "Response to oid : $response =
$record->{'oids'}{$response}\n";
}
}
#print "============================\n";
}

I am thoroughly at this point :(

= Jason

-----Original Message-----
From: Wiggins d Anconia [mailto:wiggins@danconia.org]
Sent: Thursday, March 25, 2004 10:45 AM
To: jason_normandin@charter.net; beginners@perl.org; Normandin, Jason
Subject: RE: Hash Help Needed !


> jason_normandin@charter.net <jason_normandin@charter.net> wrote:


[snip]

> :
> : print "Time : $record->{time}\n";
> : print "IP : $record->{ip_addr}\n";
> : foreach my $response ($record->{keys %response_values} )


In addition to what Charles already stated, once you have cleared up the
quoting problem and gotten your hash to store properly, then you will
need to access the hash reference of the key in the main hash using
'oids' . In other words, you need to index into $record using 'oids' to
get the hash reference, then take the keys of that dereferenced hash.

foreach my $response (keys %{ $record->{'oids'} }) {

I suspect you have a scoping issue with %response_values otherwise
strict would have complained, are you declaring your variables when
first used or all at the top? %response_values should have been a
temporary variable scoped only to your first loop which you didn't show.

http://danconia.org


****************************************
******************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.
This footnote also confirms that this email message has been swept by
the latest virus scan software available for the presence of computer
viruses.
****************************************
******************************


Jason Normandin

2004-03-26, 11:14 pm

Charles

I was able to get the data dumper to work.

According to the output, the oids referance is referancing the hash for
response_values:

$VAR1 = {
'oids' => '%response_values',
'time' => '03/25/2004 03:16:39'
};
$VAR1 = {
'oids' => '%response_values',
'time' => '03/25/2004 03:16:39'
};
$VAR1 = {
'oids' => '%response_values',
'time' => '03/25/2004 03:16:39'
};
$VAR1 = {
'oids' => '%response_values',
'time' => '03/25/2004 03:16:39'
};

My guess is as that hash is local, that hash does not really exist.

Should it be showing the actual data rather then the hash referance ?

Ex.
$VAR1 = {
'oids' => 'dat1=>value etc..',
'time' => '03/25/2004 03:16:39'
};

If so, what is wrong with my assignment statement ?

push @{$response_hash{$request_id}},{time => "$time",oids =>
"%response_values"};

How can I get the oids=> to populate the oids object with the vals ?

Thanks
Jason

-----Original Message-----
From: Charles K. Clarkson [mailto:cclarkson@htcomp.net]
Sent: Thursday, March 25, 2004 10:35 AM
To: jason_normandin@charter.net; beginners@perl.org
Cc: Normandin, Jason
Subject: RE: Hash Help Needed !


jason_normandin@charter.net <jason_normandin@charter.net> wrote:
:
: I have run into a situation that I am unclear on.
:
: I am making the following assignment during a loop:
:
: push @{$response_hash{$request_id}},{time => "$time",ip_addr
: => "$ip_address",oids => "%response_values"};

I didn't test your code but "%response_values" is not the
same as \%response_values or %response_values. You have just
run into the problem with unnecessarily quoting variables.
(Read perlfaq4.)

You might have wanted (White space is your friend.):

push @{ $response_hash{ $request_id } }, {
time => $time,
ip_addr => $ip_address,
oids => \%response_values,
};



:
: Where: response_values is a simple hash containing key,value
: pairs and $time and $ip_address are simple scalar vars.
:
: I can iterate through the %response_values hash after it is
: created localy using simple foreach my $value (keys
: %response_values ) syntax, but when I try to include that
: iteration when iterating the main response hash, I am not
: getting any values.
:
: I am using the following syntax:

Add this near the top of your script. It adds a function
named Dumper to your script.

use Data::Dumper 'Dumper';

:
: foreach my $request (sort keys %response_hash) {
: print "Response to request_id $request\n";
: foreach my $record(@{$response_hash{$request}}) {

Test what is in $record with the Dumper function:

print Dumper @record;
exit;

Is the result what you thought was in there?


:
: print "Time : $record->{time}\n";
: print "IP : $record->{ip_addr}\n";
: foreach my $response ($record->{keys %response_values} )
: {
: print "Response to oid : $response =
: $response_values{$response}\n";
: }
: }
:
: }

HTH,

Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328



****************************************
******************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.
This footnote also confirms that this email message has been swept by
the latest virus scan software available for the presence of computer
viruses.
****************************************
******************************


R. Joseph Newton

2004-03-26, 11:15 pm

jason_normandin@charter.net wrote:


> foreach my $response ($record->{keys %response_values} )


What is this? It looks like you are trying to use a list as a hash key. I don't think that is going to work. A hash element should take a scalar as its key, not a list:

Greetings! C:\Documents and Settings\rjnewton>perl -w
my %hash = (first => 'one thing', second => 'another', third => 'still another')
;
foreach $try_a_key ($hash{keys %hash}) {
print "$try_a_key\n";
}

^Z
Use of uninitialized value in concatenation (.) or string at - line 3.


There is one, sorta quirky, way that it can work, though:

Greetings! C:\Documents and Settings\rjnewton>perl -w
my %hash = (first => 'one thing', second => 'another', 3 => 'still another');
foreach $try_a_key ($hash{keys %hash}) {
print "$try_a_key\n";
}

^Z
still another

Of course, in the above, the foreach is superfluous, since this syntax willalway put one or fewer items in the list.

Is that what you were looking for--something keyed to the number of keys in a hash? Otherwise, you may have to go back and define your goal and steps to reach it more clearly.

Joseph



R. Joseph Newton

2004-03-26, 11:15 pm

"Normandin, Jason" wrote:

> Hi
>
> I am scoping the %response_values hash at the top. I dont understand why it
> would need to be temporary as I am referancing that hash outside of the loop
> when I iterate through.
>
> I changed the syntax to referance the oids rather then the hash name and I
> get the following error:
>
> Can't use string ("%response_values") as a HASH ref while "strict refs" in
> use at H:\nhsParseSnmpLog.pl line 72, <SNMP_L
> OG> chunk 78.
>
> Here is what I have:
>
> .. SNIP..
> use strict;
> my (%request_hash,%response_hash);
>
> .. SNIP...
> elsif ( m/RESPONSE:/ ) {
> # my
> ($time,$timeSecs,$request_id,$ip_address
,%response_values,$oid,$oid_value);


Best not to do this. it is good that they are soped within the sub, but would
be even better if you declare them at the time they are used, or just prior to
their first use.


>
> # Set these local to each record
> my @lines = split/\n/;


my %response_values;

>
> foreach my $line (@lines) {
> next if $line =~ m/REQUEST:/;
> my $timeSecs=$1 if $line =~ m/# Time (\d+)\.\d+
> seconds/;
> my $time=convertUtcToLocaltime($timeSecs);
> my $request_id=$1 if $line =~ m/\[REQUEST_ID\] (\d+)/;
>
> my $oid=$1 if $line =~ m/\[OBJECT_ID \] (.+)/;
> my $oid_value =$1 if $line =~ m/[\[COUNTER
> \]|\[GAUGE
> \]|\[INT \]|\[TICKS \]] (.+)/;
> $response_values{$oid}=$oid_value;
> }
> push @{$response_hash{$request_id}},{time => "$time",oids =>
> "%response_values"};
> }
>
> .. SNIP ..


Just snip? If this is getting long enough that you need to ship, then it is
getting too long to be in one sub.

Start at the top again. What data do you have to work with, in what form? What
kind of information do you want out of the process in what form? Unfortunately
%response_hash is so genral as to say nothing about the meaning of the data in
context.

I have the feeling that, if you take a fresh look at the original problem with a
view to what you have to work with, and what end result you want to achieve, we
can help you find much more straightforward means to get there.

Joseph

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com