mxn_mark has asked for the wisdom of the Perl Monks concerning the following question:

I'm just starting to play with references to create nested data structures. I've read through the Advanced Perl Programming (O'Reilly) on data structures and the Perl docs concerning the subject but I'm still a little shaky and/or missing something.

Basically I'm parsing a few log files to associate user name with given and last names. Not all entries have a last or given.

Sample log looks like this:

User: username1
   Last Name: last name1
   Given Name: given name1
User: username2
   Last Name: last name2
User: username3
   Given Name: given name3

I'm stepping through the log line by line and trying to create an array of hashes. Each hash has a username, givenname and lastname key. I can make the initial entry of a username but when I try to add a [last|given]name I can't seem to get the right syntax.

Specific problem line (#18 & #22):

$$user_list[$num_users -1]->{lastname} = $lastname;

Complete script:

00 #!/usr/bin/perl 01 02 # parse the user list dump from nlist into 1 tsv file 03 04 open (NLIST, $ARGV[0]) or die "Can't open nlist results\n $!"; 05 @nlist = <NLIST>; 06 close NLIST; 07 08 for $line (@nlist) { 09 # do not parse for the exceptions, all else do the following: 10 if ($line !~ /^[Object|Current|A total]/) { 11 # user | given | last name? 12 if ($line =~ /^User\: (\w+)\n/) { 13 $username = lc($1); 14 push @user_list, \{ "username" => $username, "lastname" + => "", "givenname" => ""}; 15 } elsif ($line =~ /^\tLast Name: (\w+)\n/) { 16 $lastname = lc($1); 17 $num_users = scalar @user_list; 18 $$user_list[$num_users -1]->{lastname} = $lastname; 19 } elsif ($line =~ /^\tGiven Name: (.)+\n/) { 20 $givenname = $1; 21 $num_users = scalar @user_list; 22 $$user_list[$num_users -1]->{givenname} = $givenname; 23 } 24 } 25 } 26 27 for $user (@user_list) { 28 print "User: $$user->{username}\n"; 29 print "\tLast: $$user->{lastname}\n"; 30 print "\tGiven: $$user->{givenname}\n"; 31 }

Any and all help is greatly appreciated. Thanks, Mark

Edit by tye

Replies are listed 'Best First'.
Re: Dereferencing Array of Hashes
by broquaint (Abbot) on Jul 26, 2002 at 16:38 UTC
    Remove the reference operator in front of the anonymous hash on line 14 and then change $$user_list to $user_list. If you *really* must dereference the anonymous hash reference then you'd do it like so
    ${ $user_list[$num_users - 1] }->{lastname} = $lastname;
    But you almost certainly don't want to do that. See perlreftut and perlref for more info.
    HTH

    _________
    broquaint

Re: Dereferencing Array of Hashes
by kvale (Monsignor) on Jul 26, 2002 at 17:50 UTC
    Here is how I would write this (untested):
    #!/usr/bin/perl -w # parse the user list dump from nlist into 1 tsv file my @user_list; open (NLIST, $ARGV[0]) or die "Can't open nlist results\n $!"; while (<NLIST>) { # do not parse for the exceptions, all else do the following: unless (/^[Object|Current|A total]/) { # user | given | last name? if (/^User\: (\w+)\n/) { push @user_list, { username => lc($1), lastname => "", givenn +ame => ""}; } elsif (/^\tLast Name: (\w+)\n/) { $user_list[-1]->{lastname} = lc $1; } elsif (/^\tGiven Name: (.)+\n/) { $user_list[-1]->{givenname} = $1; } } } close NLIST; for my $user (@user_list) { print "User: $user->{username}\n"; print "\tLast: $user->{lastname}\n"; print "\tGiven: $user->{givenname}\n"; }
    -Mark
Re: Dereferencing Array of Hashes
by ehdonhon (Curate) on Jul 26, 2002 at 16:46 UTC

    If you put <code> and </code> tags around your actual perl code, it will be easier for us to follow.