Read a hash

  • Follow


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.
0
Reply dnlchen (18) 4/27/2011 11:28:47 PM

DanielC <dnlchen@gmail.com> wrote:
> 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;


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


>     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.


-- 
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.
0
Reply Tad 4/28/2011 12:01:42 AM


In article
<022eb4e5-074c-46e1-b8f7-3d872ab353c9@h36g2000pro.googlegroups.com>,
DanielC <dnlchen@gmail.com> wrote:

> 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.

-- 
Jim Gibson
0
Reply Jim 4/28/2011 12:07:55 AM

On Apr 27, 5:01=A0pm, Tad McClellan <ta...@seesig.invalid> wrote:
> DanielC <dnlc...@gmail.com> wrote:
> > INPUT (tt):
>
> > INFO - {
> > =A0 =A0 =A0 =A0 =A0 'Result' =3D> 'failure',
> > =A0 =A0 =A0 =A0 =A0 'Id' =3D> '1564',
> > =A0 =A0 =A0 =A0 =A0 'dataRecv' =3D> 'adfasdfi',
> > =A0 =A0 =A0 =A0 =A0 'dataSent' =3D> 'rqerqerer',
> > =A0 =A0 =A0 =A0 =A0 'elapsedTime' =3D> '7.023359',
> > =A0 =A0 =A0 =A0 =A0 'externalId' =3D> 'AI2JL4PBLG',
> > =A0 =A0 =A0 =A0 =A0 'responseCode' =3D> '0',
> > =A0 =A0 =A0 =A0 =A0 'responseMsg' =3D> 'n/a',
> > =A0 =A0 =A0 =A0 =A0 'sentAt' =3D> '2011-04-27 00:08:02',
> > =A0 =A0 =A0 =A0 =A0 'serviceId' =3D> '13',
> > =A0 =A0 =A0 =A0 =A0 'serviceName' =3D> 'abc',
> > =A0 =A0 =A0 =A0 =A0 'timeInQueue' =3D> 1
> > =A0 =A0 =A0 =A0 }
>
> > INFO - {
> > =A0 =A0 =A0 =A0 =A0 'Result' =3D> 'failure',
> > =A0 =A0 =A0 =A0 =A0 'Id' =3D> '1565',
> > =A0 =A0 =A0 =A0 =A0 'dataRecv' =3D> 'asdfghjkl',
> > =A0 =A0 =A0 =A0 =A0 'dataSent' =3D> 'qwerrtyu',
> > =A0 =A0 =A0 =A0 =A0 'elapsedTime' =3D> '1.106637',
> > =A0 =A0 =A0 =A0 =A0 'externalId' =3D> 'AI2JL4X1EN',
> > =A0 =A0 =A0 =A0 =A0 'responseCode' =3D> '410',
> > =A0 =A0 =A0 =A0 =A0 'responseMsg' =3D> 'Customer account not active',
> > =A0 =A0 =A0 =A0 =A0 'sentAt' =3D> '2011-04-27 00:14:02',
> > =A0 =A0 =A0 =A0 =A0 'serviceId' =3D> '13',
> > =A0 =A0 =A0 =A0 =A0 'serviceName' =3D> 'def',
> > =A0 =A0 =A0 =A0 =A0 'timeInQueue' =3D> 1
> > =A0 =A0 =A0 =A0 }
>
> > SCRIPT (test.pl):
> > #!/usr/bin/perl -w
> > #
>
> > my %hash;
> > local $/ =3D "\n\n";
> > while (my $line =3D <>)
> > {
> > =A0 =A0 $line =3D~ s/INFO - {/(/;
> > =A0 =A0 $line =3D~ s/}/)/;
> > =A0 =A0 %hash =3D $line;
>
> =A0 =A0 %hash =3D eval $line; =A0# Danger Will Robinson!
>
> > =A0 =A0 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.
>
> --
> 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 =3D eval { $line };
0
Reply DanielC 4/28/2011 12:47:07 AM

On Apr 27, 5:07=A0pm, Jim Gibson <jimsgib...@gmail.com> wrote:
> In article
> <022eb4e5-074c-46e1-b8f7-3d872ab35...@h36g2000pro.googlegroups.com>,
>
>
>
>
>
>
>
>
>
> DanielC <dnlc...@gmail.com> wrote:
> > INPUT (tt):
>
> > INFO - {
> > =A0 =A0 =A0 =A0 =A0 'Result' =3D> 'failure',
> > =A0 =A0 =A0 =A0 =A0 'Id' =3D> '1564',
> > =A0 =A0 =A0 =A0 =A0 'dataRecv' =3D> 'adfasdfi',
> > =A0 =A0 =A0 =A0 =A0 'dataSent' =3D> 'rqerqerer',
> > =A0 =A0 =A0 =A0 =A0 'elapsedTime' =3D> '7.023359',
> > =A0 =A0 =A0 =A0 =A0 'externalId' =3D> 'AI2JL4PBLG',
> > =A0 =A0 =A0 =A0 =A0 'responseCode' =3D> '0',
> > =A0 =A0 =A0 =A0 =A0 'responseMsg' =3D> 'n/a',
> > =A0 =A0 =A0 =A0 =A0 'sentAt' =3D> '2011-04-27 00:08:02',
> > =A0 =A0 =A0 =A0 =A0 'serviceId' =3D> '13',
> > =A0 =A0 =A0 =A0 =A0 'serviceName' =3D> 'abc',
> > =A0 =A0 =A0 =A0 =A0 'timeInQueue' =3D> 1
> > =A0 =A0 =A0 =A0 }
>
> > INFO - {
> > =A0 =A0 =A0 =A0 =A0 'Result' =3D> 'failure',
> > =A0 =A0 =A0 =A0 =A0 'Id' =3D> '1565',
> > =A0 =A0 =A0 =A0 =A0 'dataRecv' =3D> 'asdfghjkl',
> > =A0 =A0 =A0 =A0 =A0 'dataSent' =3D> 'qwerrtyu',
> > =A0 =A0 =A0 =A0 =A0 'elapsedTime' =3D> '1.106637',
> > =A0 =A0 =A0 =A0 =A0 'externalId' =3D> 'AI2JL4X1EN',
> > =A0 =A0 =A0 =A0 =A0 'responseCode' =3D> '410',
> > =A0 =A0 =A0 =A0 =A0 'responseMsg' =3D> 'Customer account not active',
> > =A0 =A0 =A0 =A0 =A0 'sentAt' =3D> '2011-04-27 00:14:02',
> > =A0 =A0 =A0 =A0 =A0 'serviceId' =3D> '13',
> > =A0 =A0 =A0 =A0 =A0 'serviceName' =3D> 'def',
> > =A0 =A0 =A0 =A0 =A0 'timeInQueue' =3D> 1
> > =A0 =A0 =A0 =A0 }
>
> > SCRIPT (test.pl):
> > #!/usr/bin/perl -w
> > #
>
> > my %hash;
> > local $/ =3D "\n\n";
> > while (my $line =3D <>)
> > {
> > =A0 =A0 $line =3D~ s/INFO - {/(/;
> > =A0 =A0 $line =3D~ s/}/)/;
> > =A0 =A0 %hash =3D $line;
> > =A0 =A0 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 =3D ( $line =3D~ /'[^']*'/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.
>
> --
> Jim Gibson

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


#!/usr/bin/perl -w
#

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

print "$hash{sentAt}\n";
0
Reply DanielC 4/28/2011 12:55:11 AM

DanielC <dnlchen@gmail.com> writes:

> 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. 

-- 
John Bokma                                                               j3b

Blog: http://johnbokma.com/    Facebook: http://www.facebook.com/j.j.j.bokma
    Freelance Perl & Python Development: http://castleamber.com/
0
Reply John 4/28/2011 1:15:17 AM

DanielC <dnlchen@gmail.com> wrote:
> On Apr 27, 5:01 pm, Tad McClellan <ta...@seesig.invalid> wrote:
>> DanielC <dnlc...@gmail.com> wrote:

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

> Yes, it works. I tried this before but it didn't get the right output.
> Why?
>
> %hash = eval { $line };


Perl has 2 functions that are both name "eval".

The 1st one is "eval EXPR" and the 2nd one is "eval BLOCK".

The docs for eval BLOCK explain it:

    In the second form, the code within the BLOCK is parsed only once

So, after the eval BLOCK is parsed once, you have the same as:

    %hash = '( key => value, other => value )';

The RHS is a single string, so you get the "odd number" warning.


-- 
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.
0
Reply Tad 4/28/2011 1:51:21 AM

DanielC <dnlchen@gmail.com> wrote:
> On Apr 27, 5:07 pm, Jim Gibson <jimsgib...@gmail.com> wrote:
>> In article
>> <022eb4e5-074c-46e1-b8f7-3d872ab35...@h36g2000pro.googlegroups.com>,
>> DanielC <dnlc...@gmail.com> wrote:

>> > local $/ = "\n\n";
>> > while (my $line = <>)


Naming a variable 'line" when it does not contain a line
is a silly thing to do.


>> my %hash = ( $line =~ /'[^']*'/g );
>>
>> That probably doesn't work,


Right.

It would have been better to not post that line, as untested/unworking
code is likely to lead off into the woods rather than helping.


> Why I did "%hash = $line;" is because I had tested a script. 


Huh?

That makes no sense...


> BTW, I
> don't understand - my %hash = ( $line =~ /'[^']*'/g );


The parens don't do anything, so they should not be there.

The docs for m//g (perlop.pod) say:

    In list context, it returns a list of the
    substrings matched by any capturing parentheses in the regular
    expression.  If there are no parentheses, it returns a list of all
    the matched strings, as if there were parentheses around the whole
    pattern.

So Jim's code will end up with keys and values with single quotes in them...


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

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

which ends up being:

    my %hash = ('Result', 'failure','Id', '1565', ...);


-- 
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.
0
Reply Tad 4/28/2011 2:27:04 AM

>>>>> "TM" == Tad McClellan <tadmc@seesig.invalid> writes:

  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

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 4/28/2011 4:39:09 AM

Uri Guttman wrote:
>>>>>> "TM" == Tad McClellan<tadmc@seesig.invalid>  writes:
>
>    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. :)

If only there were some parser, somewhere, that could handle
this...

:-)

   BugBear
0
Reply bugbear 4/28/2011 2:23:56 PM

9 Replies
688 Views

(page loaded in 0.149 seconds)

Similiar Articles:













7/25/2012 12:07:32 PM


Reply: