in reply to printing array reference and storing this data in a hash.

++++ for line numbers in your code, -- for the mess in the intro, makes ++ ;-)

Answer to your first question: change line 27 to

print $dub_key,Dumper($dub_values);

More critics:

hth,
--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

Replies are listed 'Best First'.
Re^2: printing array reference and storing this data in a hash.
by mikejones (Scribe) on Dec 19, 2006 at 17:23 UTC
    OK understood and thank you! It is working now. quick question though...I read perldoc -f split and it made no mention of LIMIT in brackets in split /PATTERN/,EXPR,LIMIT Is this a trick? I know that it is spliting by fields like awk '{print $3}' /etc/passwd, but can anymore provide more detail? thank you
      The brackets are an anonymous array constructor. See perlref.
      $var = [ split /:/, $_ ];

      means "make an anonymous array (an array reference) and insert into it the results of the split operation; then assign the reference to the variable $var".

      More about split:

      $_ = "Fracassus Cacus Eryx Anteus"; # see Acme::MetaSyntactic $foo = split; # '4' $foo = split /\s+/, $_; # '4' ($foo) = split /\s+/, $_; # ('Fracassus') ($foo, $bar) = split /\s+/, $_; # ('Fracassus', 'Cacus') ($foo, $bar) = split /\s+/, $_, 2; # ('Fracassus', 'Cacus Eryx An +teus') ($foo, $bar) = split /\s+/, $_, 1; # ('Fracassus Cacus Eryx Anteu +s', '') ($foo) = split /\s+/, $_, 1; # ('Fracassus') ($foo) = (split /\s+/, $_,) [2]; # ('Eryx')

      It's odd that a split with LIMIT 1 behaves different when assigning to a list with a single or two variables; but it does. That's why I prefer to say

      $foo = (split /\s+/, $_) [0];

      if I want just the first element of the resulting list. The (split)[0] thingy means "give me the element 0 of the list returned by split".

      Thanks to BooK++ for Acme::MetaSyntactic

      --shmem

      update: added missing backslashes to /s+/ :~}

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        cool thanks for the detail, but now I have played a little with certain fields of a /etc/passwd file and I am back to the original problem...its printing the hash address not the actual values. All I need is to store the name,uid,gid and comments into a hash from the @{$dublin_aref} which is the glob of passwd files opened via <FILE>. thank you
        use strict; use warnings; use diagnostics; my @dublinaray = glob("/home/user/passwd.*"); my $dublin_aref = \@dublinaray; my %dublin_hosts = (); my (@tmp_values,@dub_values,) = (); my ($dub_key,$name,$uid,$gid,$cmts,$dub_values); parse_file(); sub parse_file { foreach my $element ( @{$dublin_aref} ) { { local *FILE; open (FILE, "+<$element") or die "dublin file '$element' did not o +pen: $!"; local $/ = undef; ($dub_key) = $element =~ m|\.(\w+\.\w+)\z|i; ($name) = (split /:/, <FILE>) [0]; ($uid) = (split /:/, <FILE>) [2]; ($gid) = (split /:/, <FILE>) [3]; ($cmts) = (split /:/, <FILE>) [4]; @tmp_values = ($name,$uid,$gid,$cmts); $dub_values = \@tmp_values; push ( @{$dublin_hosts{$dub_key}}, $dub_values ); } } while ( ($dub_key,$dub_values) = each %dublin_hosts ) { print Dumper("$dub_key => @{$dub_values}\n"); }
        The code below works, yet I am still trying to figure out why the above code does not:
        open (FILE, "+</cygdrive/c/temp/passwd.oftappp1.hpux"); my (@values,$name,$uid,$gid,$comments) = (); foreach my $file (<FILE>) { ($name) = (split /:/ , $file) [0]; ($uid) = (split /:/ , $file) [2]; ($gid) = (split /:/ , $file) [3]; ($comments) = (split /:/ , $file) [4]; @values = ($name,$uid,$gid,$comments); print join ("\t", @values,"\n"); }
        was wondering if you saw my most recent response? thx!
      I'll admit I just skimmed a bit, but can't find what you're talking about. Are you talking about shmem's solution for your line 19 similar to:
      $foo = ( split /pattern/, $string ) [ number ];
      ??? If that's the case, then look very carefully and you'll realize that the bracketed portion is not the optional third parameter to split(). The construct:
      ( returns_a_list )[ index ]
      or
      ( returns_a_list )[ index, index ]
      is called an array slice (or list slice). The indexes are the only ones from the list/array that end up being returned. The parentheses are there basically to bind the index to the whole list that's being returned.

      List slices are a very handy idiom, and can be used to great effect in Perl.

      Like lots of conveniences in Perl or any other higher-level dynamic language, this can also be abused since there are sometimes much more efficient solutions. Learning when to use slices and when to avoid generating the whole list to use just part of it is a classic machine time/programmer time trade-off. I always try to err on the side of saving programmer time until I actually need to worry about a specific hotspot in a program.


      Christopher E. Stith
        cool thanks for the detail, but now I have played a little with certain fields of a /etc/passwd file and I am back to the original problem...its printing the hash address not the actual values. All I need is to store the name,uid,gid and comments into a hash from the @{$dublin_aref} which is the glob of passwd files opened via <FILE>. thank you
        use strict; use warnings; use diagnostics; my @dublinaray = glob("/home/user/passwd.*"); my $dublin_aref = \@dublinaray; my %dublin_hosts = (); my (@tmp_values,@dub_values,) = (); my ($dub_key,$name,$uid,$gid,$cmts,$dub_values); parse_file(); sub parse_file { foreach my $element ( @{$dublin_aref} ) { { local *FILE; open (FILE, "+<$element") or die "dublin file '$element' did not o +pen: $!"; local $/ = undef; ($dub_key) = $element =~ m|\.(\w+\.\w+)\z|i; ($name) = (split /:/, <FILE>) [0]; ($uid) = (split /:/, <FILE>) [2]; ($gid) = (split /:/, <FILE>) [3]; ($cmts) = (split /:/, <FILE>) [4]; @tmp_values = ($name,$uid,$gid,$cmts); $dub_values = \@tmp_values; push ( @{$dublin_hosts{$dub_key}}, $dub_values ); } } while ( ($dub_key,$dub_values) = each %dublin_hosts ) { print Dumper("$dub_key => @{$dub_values}\n"); }
        The code below works, yet I am still trying to figure out why the above code does not:
        open (FILE, "+</cygdrive/c/temp/passwd.oftappp1.hpux"); my (@values,$name,$uid,$gid,$comments) = (); foreach my $file (<FILE>) { ($name) = (split /:/ , $file) [0]; ($uid) = (split /:/ , $file) [2]; ($gid) = (split /:/ , $file) [3]; ($comments) = (split /:/ , $file) [4]; @values = ($name,$uid,$gid,$comments); print join ("\t", @values,"\n"); }
        I ran it in debug mode and I am seeing:
        perl -d uid_check.pl Loading DB routines from perl5db.pl version 1.22 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(uid_check.pl:22): $ENV{"PATH"} = qq(/usr/bin:/bin:/home/ +dbsmith:/home/dbsmith/McGaw); DB<1> n main::(uid_check.pl:23): delete @ENV{qw (IFS CDPATH ENV KSH_ENV + BASH_ENV)}; DB<1> n main::(uid_check.pl:27): open (LOG, ">>/tmp/uid_ck.log") or war +n "uid_ck.log did not open $!"; DB<1> n main::(uid_check.pl:29): my $overide = $SIG{__DIE__}; ## get + error handler currently assigned 2 die main::(uid_check.pl:30): $SIG{__DIE__} = sub { DB<1> n main::(uid_check.pl:34): }; DB<1> n main::(uid_check.pl:38): my @dublinaray = glob("/home/dbsmith/ +passwd.*"); DB<1> n main::(uid_check.pl:39): my $dublin_aref = \@dublinaray; DB<1> n main::(uid_check.pl:40): my @mcgawaray = glob("/home/dbsmith/ +McGaw/passwd.*"); DB<1> n main::(uid_check.pl:41): my $mcgaw_aref = \@mcgawaray; DB<1> n main::(uid_check.pl:42): my (%dublin_hosts,%mcgaw_hosts) = (); DB<1> n main::(uid_check.pl:43): my (@tmp_values,@dub_values,) = (); DB<1> n main::(uid_check.pl:44): my ($dub_key,$name,$uid,$gid,$cmts,$mc +g_key,$dub_values); DB<1> n main::(uid_check.pl:52): foreach my $element ( @{$dublin_ar +ef} ) { DB<1> n main::(uid_check.pl:52): foreach my $element ( @{$dublin_ar +ef} ) { DB<1> n main::(uid_check.pl:53): { local *FILE; DB<1> n main::(uid_check.pl:53): { local *FILE; DB<1> n main::(uid_check.pl:54): open (FILE, "+<$element") or d +ie "dublin file '$element' did not open: $!"; DB<1> n main::(uid_check.pl:55): local $/ = undef; DB<1> n main::(uid_check.pl:56): ($dub_key) = $element =~ m| +\.(\w+\.\w+)\z|i; DB<1> n main::(uid_check.pl:57): ($name) = (split /:/, <FILE>) +[0]; ## ONLY ONE THAT WORKS ## DB<1> print $dub_key; admbakp1.hpux DB<2> n main::(uid_check.pl:58): ($uid) = (split /:/, <FILE>) +[2]; DB<2> print $name; root DB<3> n main::(uid_check.pl:59): ($gid) = (split /:/, <FILE>) +[3]; DB<3> print $uid; Use of uninitialized value in print at (eval 31)[/opt/perl/lib/5.8.2/perl5db.pl:618] line 2, <FILE> chunk 1 + (#1) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl tells you what ope +ration you used the undefined value in. Note, however, that perl optimiz +es your program and the operation displayed in the warning may not necessa +rily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer +to the concatenation (.) operator, even though there is no . in your program. Use of uninitialized value in print at (eval 31)[/opt/perl/lib/5.8.2/p +erl5db.pl:618] line 2, <FILE> chunk 1. diagnostics::warn_trap('Use of uninitialized value in print at + (eval 31)[/opt/perl/li...') called at (eval 31)[/opt/perl/lib/5.8.2/ +perl5db.pl:618] line 2 eval '($@, $!, $^E, $,, $/, $\\, $^W) = @saved;package main; $ +^D = $^D | $DB::db_stop; print $uid;; ;' called at /opt/perl/lib/5.8.2/perl5db.pl line 618 DB::eval called at /opt/perl/lib/5.8.2/perl5db.pl line 3314 DB::DB called at uid_check.pl line 59 DB<4> q