Read a hash

D

DanielC

INPUT (tt):

INFO - {
'Result' => 'failure',
'Id' => '1564',
'dataRecv' => 'adfasdfi',
'dataSent' => 'rqerqerer',
'elapsedTime' => '7.023359',
'externalId' => 'AI2JL4PBLG',
'responseCode' => '0',
'responseMsg' => 'n/a',
'sentAt' => '2011-04-27 00:08:02',
'serviceId' => '13',
'serviceName' => 'abc',
'timeInQueue' => 1
}

INFO - {
'Result' => 'failure',
'Id' => '1565',
'dataRecv' => 'asdfghjkl',
'dataSent' => 'qwerrtyu',
'elapsedTime' => '1.106637',
'externalId' => 'AI2JL4X1EN',
'responseCode' => '410',
'responseMsg' => 'Customer account not active',
'sentAt' => '2011-04-27 00:14:02',
'serviceId' => '13',
'serviceName' => 'def',
'timeInQueue' => 1
}


SCRIPT (test.pl):
#!/usr/bin/perl -w
#

my %hash;
local $/ = "\n\n";
while (my $line = <>)
{
$line =~ s/INFO - {/(/;
$line =~ s/}/)/;
%hash = $line;
print "$hash{'sentAt'}\n";
}

I know how to read the input line by line, then put them into a hash.
Here I just want to try read one section of data into a hash. However
it failed with below errors. Can someone shed some light on this
script and make it work?

$ cat tt|perl test.pl
Odd number of elements in hash assignment at test.pl line 10, <> chunk
1.
Use of uninitialized value in print at test.pl line 11, <> chunk 1.
Odd number of elements in hash assignment at test.pl line 10, <> chunk
2.
Use of uninitialized value in print at test.pl line 11, <> chunk 2.
 
J

Jim Gibson

DanielC said:
INPUT (tt):

INFO - {
'Result' => 'failure',
'Id' => '1564',
'dataRecv' => 'adfasdfi',
'dataSent' => 'rqerqerer',
'elapsedTime' => '7.023359',
'externalId' => 'AI2JL4PBLG',
'responseCode' => '0',
'responseMsg' => 'n/a',
'sentAt' => '2011-04-27 00:08:02',
'serviceId' => '13',
'serviceName' => 'abc',
'timeInQueue' => 1
}

INFO - {
'Result' => 'failure',
'Id' => '1565',
'dataRecv' => 'asdfghjkl',
'dataSent' => 'qwerrtyu',
'elapsedTime' => '1.106637',
'externalId' => 'AI2JL4X1EN',
'responseCode' => '410',
'responseMsg' => 'Customer account not active',
'sentAt' => '2011-04-27 00:14:02',
'serviceId' => '13',
'serviceName' => 'def',
'timeInQueue' => 1
}


SCRIPT (test.pl):
#!/usr/bin/perl -w
#

my %hash;
local $/ = "\n\n";
while (my $line = <>)
{
$line =~ s/INFO - {/(/;
$line =~ s/}/)/;
%hash = $line;
print "$hash{'sentAt'}\n";
}

I know how to read the input line by line, then put them into a hash.
Here I just want to try read one section of data into a hash. However
it failed with below errors. Can someone shed some light on this
script and make it work?

The variable $line is _data_. You are hoping that Perl will treat it as
_code_, but it does not. So your %hash is assigned one key ($line) and
no values. Hence the error about an odd number of elements. When the
value for 'sentAt' is fetched, it is null because it does not exist in
the hash, hence the 'uninitialized value in print' error.

You could try running eval on your data to treat it as code, but that
is not recommended.

Your only hope is to come up with a regular expression that can extract
keys and values from your string, capture them into an array or list,
and assign the array/list to your hash. Something like:

my %hash = ( $line =~ /'[^']*'/g );

That probably doesn't work, and I don't have time to test and fix it,
but somebody smarter than me will no doubt produce a working version
forthwith.
 
D

DanielC

    %hash = eval $line;  # Danger Will Robinson!




--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.

Yes, it works. I tried this before but it didn't get the right output.
Why?

%hash = eval { $line };
 
D

DanielC

DanielC said:
INPUT (tt):
INFO - {
          'Result' => 'failure',
          'Id' => '1564',
          'dataRecv' => 'adfasdfi',
          'dataSent' => 'rqerqerer',
          'elapsedTime' => '7.023359',
          'externalId' => 'AI2JL4PBLG',
          'responseCode' => '0',
          'responseMsg' => 'n/a',
          'sentAt' => '2011-04-27 00:08:02',
          'serviceId' => '13',
          'serviceName' => 'abc',
          'timeInQueue' => 1
        }
INFO - {
          'Result' => 'failure',
          'Id' => '1565',
          'dataRecv' => 'asdfghjkl',
          'dataSent' => 'qwerrtyu',
          'elapsedTime' => '1.106637',
          'externalId' => 'AI2JL4X1EN',
          'responseCode' => '410',
          'responseMsg' => 'Customer account not active',
          'sentAt' => '2011-04-27 00:14:02',
          'serviceId' => '13',
          'serviceName' => 'def',
          'timeInQueue' => 1
        }
SCRIPT (test.pl):
#!/usr/bin/perl -w
#
my %hash;
local $/ = "\n\n";
while (my $line = <>)
{
    $line =~ s/INFO - {/(/;
    $line =~ s/}/)/;
    %hash = $line;
    print "$hash{'sentAt'}\n";
}
I know how to read the input line by line, then put them into a hash.
Here I just want to try read one section of data into a hash. However
it failed with below errors. Can someone shed some light on this
script and make it work?

The variable $line is _data_. You are hoping that Perl will treat it as
_code_, but it does not. So your %hash is assigned one key ($line) and
no values. Hence the error about an odd number of elements. When the
value for 'sentAt' is fetched, it is null because it does not exist in
the hash, hence the 'uninitialized value in print' error.

You could try running eval on your data to treat it as code, but that
is not recommended.

Your only hope is to come up with a regular expression that can extract
keys and values from your string, capture them into an array or list,
and assign the array/list to your hash. Something like:

my %hash = ( $line =~ /'[^']*'/g );

That probably doesn't work, and I don't have time to test and fix it,
but somebody smarter than me will no doubt produce a working version
forthwith.


$ cat tt|perl test.pl
Odd number of elements in hash assignment at test.pl line 10, <> chunk
1.
Use of uninitialized value in print at test.pl line 11, <> chunk 1.
Odd number of elements in hash assignment at test.pl line 10, <> chunk
2.
Use of uninitialized value in print at test.pl line 11, <> chunk 2.

Why I did "%hash = $line;" is because I had tested a script. BTW, I
don't understand - my %hash = ( $line =~ /'[^']*'/g );


#!/usr/bin/perl -w
#

my %hash = (
'Result' => 'failure',
'Id' => '1565',
'dataRecv' => 'asdfghjkl',
'dataSent' => 'qwerrtyu',
'elapsedTime' => '1.106637',
'externalId' => 'AI2JL4X1EN',
'responseCode' => '410',
'responseMsg' => 'Customer account not active',
'sentAt' => '2011-04-27 00:14:02',
'serviceId' => '13',
'serviceName' => 'def',
'timeInQueue' => 1
);

print "$hash{sentAt}\n";
 
J

John Bokma

DanielC said:
INPUT (tt):

INFO - {
'Result' => 'failure',
'Id' => '1564',
'dataRecv' => 'adfasdfi',
'dataSent' => 'rqerqerer',
'elapsedTime' => '7.023359',
'externalId' => 'AI2JL4PBLG',
'responseCode' => '0',
'responseMsg' => 'n/a',
'sentAt' => '2011-04-27 00:08:02',
'serviceId' => '13',
'serviceName' => 'abc',
'timeInQueue' => 1
}

If you have any control over the input format you might want to change
to YAML, or use Data::Dumper. I recommend/prefer the former.
 
U

Uri Guttman

TM> Choose a more meaningful name, remove the unneeded parens and add the
TM> needed parens:

TM> my %hash = $chunk =~ /'([^']*)'/g;

and that fails because of this data line:

'timeInQueue' => 1

so it will also likely spit out an odd number of hash elements warning.

one way to fix this is to make the regex grab the left part (always in
'') skip => and whitespace and then the right part which is either in ''
or a digit (word?) string. i leave it as an exercise. :)

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top