Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

assigning to a hash via split

by aardvark (Pilgrim)
on Feb 19, 2001 at 06:43 UTC ( #59325=perlquestion: print w/ replies, xml ) Need Help??
aardvark has asked for the wisdom of the Perl Monks concerning the following question:

Happy Sunday Everybody,
Is there a way to assign to a hash via split?
Here's what I've got so far:

sub read_passwd { open IN, '/etc/passwd' or die "can't open IN $!\n"; my %users; my @fields = qw(name pword uid gid fullname home shell); while (<IN>) { chomp; my %rec; my @data = split(/:/); $rec{$fields[0]} = $data[0]; $rec{$fields[1]} = $data[1]; $rec{$fields[2]} = $data[2]; $rec{$fields[3]} = $data[3]; $rec{$fields[4]} = $data[4]; $rec{$fields[5]} = $data[5]; $rec{$fields[6]} = $data[6]; $users{$rec{name}} = \%rec; } return (\%users); }
Does anybody know of a better way to do this?
Specifically, is there a way to assign to %rec during the split?
Then, if I add another field all I have to do is add it to @fields.

I really want less typing (Laziness, Impatience) so I can have more time to work on my Hubris. ;-)

Get Strong Together!!

Replies are listed 'Best First'.
(dkubb) Re: (2) Parsing the /etc/passwd file
by dkubb (Deacon) on Feb 19, 2001 at 07:24 UTC

    There is an easier way to do what you want, using a CPAN module called Unix::PasswdFile:

    use Unix::PasswdFile; my $pw = Unix::PasswdFile->new('/etc/passwd') or die 'Could not open /etc/passwd'; my %users = map { $_ => [$ps->user($_)] } $pw->users;

    This will create the %users hash without you needing to worry about the structure of the /etc/passwd file.

Re: assigning to a hash via split
by danger (Priest) on Feb 19, 2001 at 06:48 UTC

    You can use a hash-slice to assign a list of values to a list of keys directly. Your inner while loop becomes:

    while (<IN>) { chomp; my %rec; @rec{@fields} = split /:/; $users{$rec{name}} = \%rec; }
Re: assigning to a hash via split
by japhy (Canon) on Feb 19, 2001 at 06:49 UTC
    Sure. Here's some short code for you:
    while (<IN>) { chomp; my ($name) = /([^:]+)/; @{ $users{$name} }{ @fields } = split /:/; }
    I basically create the hash reference and assign to it all at once.
    update: down with temporary variables, up with one-liners.
    chomp(@{$users{(/([^:]+)/)[0]}}{@fields} = split /:/) while <IN>;

    japhy -- Perl and Regex Hacker
Re: assigning to a hash via split
by BlueLines (Hermit) on Feb 19, 2001 at 07:19 UTC
    You mayt also want to check out getpwent, which handles the iteration over the passwd(5) file and removes the need for the split (and open) in the first place.


    Disclaimer: This post may contain inaccurate information, be habit forming, cause atomic warfare between peaceful countries, speed up male pattern baldness, interfere with your cable reception, exile you from certain third world countries, ruin your marriage, and generally spoil your day. No batteries included, no strings attached, your mileage may vary.
      Ooh, good catch. You get a ++ from me, and I offer this in reply:
      sub buildUserHash { use User::pwent; my %users; while (my $obj = getpwent) { $users{$obj->name} = $obj } return \%users; }
      Now, you have a hash of User::pwent objects.

      japhy -- Perl and Regex Hacker

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://59325]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2016-07-25 00:23 GMT
Find Nodes?
    Voting Booth?
    What is your favorite alternate name for a (specific) keyboard key?

    Results (221 votes). Check out past polls.