Read a hash

Discussion in 'Perl Misc' started by DanielC, Apr 28, 2011.

  1. DanielC

    DanielC Guest

    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.
     
    DanielC, Apr 28, 2011
    #1
    1. Advertising

  2. DanielC

    Jim Gibson Guest

    In article
    <>,
    DanielC <> 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
     
    Jim Gibson, Apr 28, 2011
    #2
    1. Advertising

  3. DanielC

    DanielC Guest

    On Apr 27, 5:01 pm, Tad McClellan <> wrote:
    > DanielC <> 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.


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

    %hash = eval { $line };
     
    DanielC, Apr 28, 2011
    #3
  4. DanielC

    DanielC Guest

    On Apr 27, 5:07 pm, Jim Gibson <> wrote:
    > In article
    > <>,
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > DanielC <> 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


    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";
     
    DanielC, Apr 28, 2011
    #4
  5. DanielC

    John Bokma Guest

    DanielC <> 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/
     
    John Bokma, Apr 28, 2011
    #5
  6. DanielC

    Uri Guttman Guest

    >>>>> "TM" == Tad McClellan <> 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 ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Apr 28, 2011
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Red Orchid
    Replies:
    3
    Views:
    1,062
  2. Pieter Claassen
    Replies:
    1
    Views:
    1,128
    CBFalconer
    Aug 4, 2004
  3. Bo Peng
    Replies:
    4
    Views:
    798
  4. rp
    Replies:
    1
    Views:
    555
    red floyd
    Nov 10, 2011
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    639
    David A. Black
    Jul 2, 2008
Loading...

Share This Page