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

Can someone plesae explain why I am getting below errors?
#!/usr/bin/perl -w use strict; my $user; my $tty; my $count; my @where; my %count = (); my %where = (); foreach $_ (`who`) { ($user,$tty) = /(\S+)\s+(\S+)/; $count{$user}++; $where{$user}{$tty}++; } foreach (sort keys %count) { if ($count{$_} == 1) { print "user $_ is ONLY logged in at one place "; print $where->{$_}; } else { print "user $_ is logged in at: "; @where = sort keys %{$where{$_}}; print "@where\n"; } } ~
When I run it I get
~/script/perl/temp@myserver >./perl.tty1 Global symbol "$where" requires explicit package name at ./perl.tty1 l +ine 22. Execution of ./perl.tty1 aborted due to compilation errors. ~/script/perl/temp@myserver >

Replies are listed 'Best First'.
Re: reference question
by Joost (Canon) on Jul 28, 2007 at 22:53 UTC
    You're using a hash reference called $where, but you've only defined a hash (i.e. not a reference) named %where.

    Update: you probably want:

    print $where{$_};
    Update2: scratch that update.
    foreach (sort keys %count) { if ($count{$_} == 1) { print "user $_ is ONLY logged in at one place: "; print keys %{$where{$_}},"\n"; # print the single key } else { print "user $_ is logged in at: "; @where = sort keys %{$where{$_}}; print "@where\n"; } }
    Since $where{$user} always contains a hash ref.

      thank you that worked.
Re: reference question
by wind (Priest) on Jul 29, 2007 at 00:31 UTC
    Joost and others have already pointed out the mistake you made with references.

    However, I'd also like to point out that it would help if you simplified your code. Instead of keeping separate structures for count and the list of ttys, why not just keep those in a single hash of arrays structure.

    Also, please note that you should limit the scope of your variables to their smallest possible scope. This gives "use strict;" the best chance of helping with syntax errors and also is the most obvious way to self-document your code.
    #!/usr/bin/perl -w use strict; my %ttys_of; foreach (`who`) { my ($user, $tty) = /(\S+)\s+(\S+)/; push @{$ttys_of{$user}}, $tty; } foreach my $user (sort keys %ttys_of) { my $ttys = $ttys_of{$user}; if (@$ttys == 1) { print "user $user is ONLY logged in at one place $ttys->[0]\n" +; } else { print "user $user is logged in at: " . join(' ', sort @$ttys) +. "\n"; } }
    - Miller

    Update 4:20 UTC: Fixed this line my $ttys = @{$ttys_of{$user}};
      Something wrong ...
      ~/script/perl/temp@myserver >cat !$ cat ./perl.tty4 #!/usr/bin/perl -w use strict; my %ttys_of; foreach (`who`) { my ($user, $tty) = /(\S+)\s+(\S+)/; push @{$ttys_of{$user}}, $tty; } foreach my $user (sort keys %ttys_of) { my $ttys = @{$ttys_of{$user}}; if (@$ttys == 1) { print "user $user is ONLY logged in at one place $ttys +->[0]\n"; } else { print "user $user is logged in at: " . join(' ', sort +@$ttys) . "\n"; } } ~/script/perl/temp@myserver >./!$ ././perl.tty4 Can't use string ("1") as an ARRAY ref while "strict refs" in use at . +/./perl.tty4 line 15. main::(././perl.tty4:13): my $ttys = @{$ttys_of{$user}}; DB<1> main::(././perl.tty4:13): my $ttys = @{$ttys_of{$user}}; DB<1> main::(././perl.tty4:15): if (@$ttys == 1) { DB<1> Can't use string ("1") as an ARRAY ref while "strict refs" in use at . +/./perl.tty4 line 15, <IN> chunk 142. Debugged program terminated. Use q to quit or R to restart, use O inhibit_exit to avoid stopping after program termination, h q, h R or h O to get additional info.
        Sorry about that. That's why one should not play around with more than one version of code before posting their solution. I temporarily thought about dereferencing the array to make it simpler to access in the loop. But I personally would never do this, so I removed the temporary simplification ... almost.

        The code has been updated with the correction.

        - Miller
      thank you, I will try your code, I was just following some online tutorial.. I guess they were trying to show the easiest way to code and I wanted to modify its code. but I like your code better..!! will give it a shot. thank you.
Re: reference question
by Cabrion (Friar) on Jul 28, 2007 at 22:55 UTC
    Change
    print $where->{$_};
    to
    print $where{$_};
    $where is not a hash reference, it's a plain hash.