Re: local and my in subroutines



At 04:30 PM 2/23/09 -0800, Karyn Stump wrote:
I am trying to learn subroutines. I have seen refernces to using my and
local for passing variables so I am playing with them to try to understand
better how this all works.

I have a subroutine in the script below, printsub that errors when it is
run with

Global symbol "$name" requires explicit package name at ./user-sub.pl line
143.
Global symbol "$name" requires explicit package name at ./user-sub.pl line
144.
Execution of ./user-sub.pl aborted due to compilation error



Continued searching on the net turned up

http://perl.plover.com/FAQs/Namespaces.html

which declares "Always use my, never use local." and a good explanation of
why.

Just in case anyone else has this question and searches the archives.




This is the code pulled out of easy viewing:

sub printsub
{
local($name) = $_[0];
print "This is the value of $name in the subroutine.\n";
}

The second sub in this script works using:

my $name = shift(@_);

another example I found online.

I would appreciate some help understanding if or how local can be used in
this context. Also if there is a better/preferred way to pass this var to
the sub.

TIA,

Karyn




Here is the whole script:

#!/usr/bin/perl

use strict;
use warnings;

# Open passwd file to compare arguments to to make sure they are valid
usernames

my $pwfile = "/etc/passwd";

open (PW, "<$pwfile") or die "Can't open PW $pwfile : $!";

# Create extenions for log files as the older ones have a bz2 extension.
They will also need
# a different command to grep them than the current log file.

my @extension;
push @extension, ''; # Place null in [0] so that it will be
false the first loop for $log

my $increment = 0;
my $ext = ".bz2";

while (@extension < 6)
{
push @extension, ".$increment$ext";
$increment++;
}

my $pwf = do { local $/; <PW> };
close PW or warn "Error closing PW $!";

foreach my $user (@ARGV)
{

print "Checking $user\n";

if ($pwf !~ /\b$user\b/)
{
print "$user is not a valid login name.\n\n";
next;
}

if (-e "/usr/home/$user/.forward")
{
print "User $user has a forward file.\n\n";
my $forward = "/usr/home/$user/.forward";
open (INFO, "<$forward") or die "Can't open INFO $forward : $!";
my @lines = <INFO>;
close(INFO);
print @lines;
my $quota = `quota -v $user`;
print "User $user quota is $quota\n";
next;
}

my $count;
my $log;
my $bzcat = "/usr/bin/bzcat";

foreach my $end (@extension)
{

$log = "/var/log/maillog$end";

if ($end =~ /bz2/)
{
open (MAILLOG, '-|', "$bzcat $log") or warn "Couldn't run '$bzcat
$log': $!";
#print "That worked - Opened file with bzcat\n";
}
else
{
open (MAILLOG, $log) or warn "Couldn't open maillog $log: $!";
#print "Opened file without bzcat\n";
}

$count = 0;
while (<MAILLOG>)
{
#$count++ if /user=$user /;
$count++ if /user=\<$user/;
}
last if $count;
close MAILLOG or warn $! ? "error closing $log: $!" : "Exit status $?
from $$bzcat";
#print "Closing MAILLOG here\n";
}


if ($count)
{
$log =~ s|.*archives/||; # Strip out path before filename
print "$user checked mail $count times in $log.\n";
my $quota = `quota -v $user`;
print "User $user quota is $quota\n";

}
else
{
print "$user is not in the maillog for the last 6 months.\n";

my @directories = ("/usr/home/$user/public_html", "/usr/home/$user");

foreach my $directory (@directories)
{
if (-d $directory)
{
my @files =();
opendir DIR, $directory or die "Error reading $directory: $!n";
my @sorted = sort {-M "$directory/$a" <=> -M "$directory/$b"}
readdir(DIR);
closedir DIR;
foreach my $item (@sorted)
{
push(@files,$item) unless $item eq "." or $item eq "..";
}

my $count = @files;
if ($count > 0)
{
my $age = sprintf("%.1f",(-M "$directory/$files[0]"));
print "Newest file in $directory is $files[0] and it is $age
days old.\n";
}
else
{
print "User $user has no files in their $directory
directory.\n";
}
}
else
{
print "No $directory found.\n";
}
}

# end of directory search

}

&printsub($user);
&lastsub($user);

print "\n";

}

sub printsub
{
local($name) = $_[0];
print "This is the value of $name in the subroutine.\n";
}

sub lastsub
{
# Check for logins with last

my $name = shift(@_);
my @command1 = `last -n 1 $name`;
chomp(@command1);

if ($command1[0] eq '')
{
print "$name has not logged in since $command1[1].\n";
}
else
{
print "$command1[0].\n";
}

}



--

Karyn Stump
Network Services Manager
California Institute of the Arts
karyn@xxxxxxxxxxx
http://noc.calarts.edu

--
To unsubscribe, e-mail: beginners-unsubscribe@xxxxxxxx
For additional commands, e-mail: beginners-help@xxxxxxxx
http://learn.perl.org/



--

Karyn Stump
Network Services Manager
California Institute of the Arts
karyn@xxxxxxxxxxx
http://noc.calarts.edu
.



Relevant Pages

  • local and my in subroutines
    ... The second sub in this script works using: ... # Create extenions for log files as the older ones have a bz2 extension. ... foreach my $end ...
    (perl.beginners)
  • Re: local and my in subroutines
    ... The second sub in this script works using: ... perldoc -f getpwnam ... # Create extenions for log files as the older ones have a bz2 extension. ... foreach my $end { ...
    (perl.beginners)
  • Re: any options for foreach?
    ... > this finds all files with an extension of $1 then cuts the list so only the ... > foreach sees this as two tokens, ie. separate $var items ... > How can i make foreach use only line breaks and not white spaces as it's delimiter? ... > echoing the command shows what i hope to acheive with this script, ...
    (comp.unix.shell)
  • any options for foreach?
    ... Consider the line in my script ... this finds all files with an extension of $1 then cuts the list so only the ... How can i make foreach use only line breaks and not white spaces as it's delimiter? ...
    (comp.unix.shell)
  • Re: how to call sub by value in variable
    ... foreach my $name ... strict refs? ... If I get sub name which not exist then my script write something into system log file but still run and call other subs which exists. ...
    (comp.lang.perl.misc)