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

I'm just learning Perl (I felt the lure of the dark side after starting with Python :P). Anyways, I'm having a problem with the following short script. I believe the problem is because the value of an associative array must be a scalar (right?), but I want to store a list. Here's the script: --
my %user_dict; #stores {user : info} of all system users my @user_info; #temp list of data from USER_LIST my @online_list; #list of users currently logged in my $user; my $online; my $user_online; open (USER_LIST, 'users') or open(USER_LIST, '/etc/passwd') or die "Couldn't open: $!"; while (<USER_LIST>) { @user_info = split /:/, $_; $user_dict{$user_info[0]} = \@user_info[4,5]; } @online_list = split(' ', `/usr/bin/users`); foreach $user (keys %user_dict) { $online = 0; foreach $user_online (@online_list) { if ($user_online eq $user) { $online = 1; last; } } if ($online) { print "Online text box\n"; } else { print "Offline text box\n"; } print "User Info on $user: $user_dict{$user}\n"; } --
Instead of printing the 5th and 6th
fields of /etc/passwd (homedir + shell), 
it prints "User Info on root: SCALAR(0x8056d08)".

Could someone:
1) Tell me what I'm doing wrong
2) PLEASE comment on *how* I've coded this. 
I want to learn to code Perl write, and shed all the Python-esque techniques I've learned. If you were going to write the above, how would you do it? Should I be declaring all my variables at the top, or should I declare them throughout the program? TIA

Replies are listed 'Best First'.
Re: newbie - hash - array?
by rgmoore (Initiate) on Feb 11, 2000 at 11:56 UTC

    This is actually trickier than anyone has suggested. An array slice is actually just a list of scalars, not another array that you can reference. That's why you get a scalar reference from your printout; the \ is referencing the last element in the list. If you change it to $$user_dict{$user} to dereference the reference it will be the shell.

    What you actually need to do is to enclose the slice in square brackets to convert it into an anonymous array, like so:

    @user_info = split /:/; #$_ not needed, as it's the default $user_dict{$user_info[0]} = [@user_info[4,5]]; #create anonymous arra +y ... print "User Info for $user: $user_dict{$user}[0] $user_dict{$user}[1] +\n";

    I agree, though, that this probably isn't the best way of doing this. If you're not going to use the home dir and shell for anything else, there's no reason not to join them into a single scalar right away:

    @user_info = split /:/; #$_ not needed, as it's the default $user_dict{$user_info[0]} = join(" ", @user_info[4,5]); ... print "User Info for $user: $user_dict{$user}\n";

    By using a join instead of concatenating strings it will be easier to modify the information you display later.

Re: newbie - hash - array?
by setantae (Scribe) on Feb 11, 2000 at 08:22 UTC
    The coding is fine (TMTOWTDI) - The problem lies with just one line, line 10.
    My way to get it working was to modify the first block of code so it says this:
    open(USER_LIST, '/etc/passwd') or die "Couldn't open: $!"; while (<USER_LIST>) { @user_info = split /:/, $_; $user_dict{$user_info[0]} = $user_info[4] . " " . $user_info[5]; }

    I think the problem is here :
    @user_info[4,5]; #same as ($user_info[4],$user_info[5]);
    although I don't know what the \ that you have there does...
    setantae@eidosnet.co.uk|setantae|http://www.setantae.uklinux.net
      The \ you're both confused about actually creates a reference to the variable it precedes. In the code, it assigns a reference to the array of @user_info[4,5] as the value of the hash.

      You need to read perldoc perlref. (Pay close attention to how you dereference a reference.)

Re: newbie - hash - array?
by Anonymous Monk on Feb 11, 2000 at 11:17 UTC
    i dont think u have any problem with the code. u have refernced the values of the keys at line 11 so when u r printing u should dereference the values. here u r not doing that so it is returning the address of the array elements u have referenced use print "User Info on $user: @{$user_dict{$user}}\n"; instead of ur last print statement.it should work.