I'm not necessarily looking for a better way to do this, rather an explanations of the output would greatly be appreciated. Recently, a senior programmer asked me why his code worked but only for one instance. What I came to find out was that it worked every other occurrence. Here is my example:
#!/usr/bin/perl -w
use strict;
my @list_env_vars = (
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
);
foreach (@list_env_vars){
print "$_ = ".glob()."\n";
}
which output for perl 5.004:
$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =
or output for perl 5.10:
$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =
$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =
$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =
I personally have never used glob() in this fashion so I was ill equipped to answer him. I read through perldoc glob documentation and followed the File::Glob link on that page and still couldn’t find anything that would explain the output. Any help would be much appreciated.
glob
in scalar context:
In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted.
In
foreach (@list_env_vars){
print "$_ = ".glob()."\n";
}
The glob()
there really is glob($_)
. Every iteration, $_
contains the string $SERVER
. Given that the environment variable does not change, $SERVER
is expanded to the same string. First time, this string is returned. Next, the list is exhausted, so undef
is returned. Third time, we start over. ...
Clarification: It does not matter that the argument to the second call is the same as the one for the first call since there is no way to reset glob
's iterator.
You can see this more clearly using the following example (current directory contains files '1.a', 1.b', '2.a' and '2.b'):
#!/usr/bin/perl -w
use strict;
my @patterns = (
'*.a',
'*.b',
);
for my $v ( @patterns ) {
print "$v = ", scalar glob($v), "\n";
}
Output:
C:\Temp> d *.a = 1.a *.b = 2.a
I would recommend accessing environment variables via the %ENV
hash:
my @list_env_vars = ($ENV{SERVER}) x 6;
or
my @list_env_vars = @ENV{qw(HOME TEMP SERVER)};
Incidentally, the reason why in 5.004 you get a variable expansion, while on 5.10 you just get your literal string back, is because on old perl, glob()
was carried out by the system shell, which just as a side-effect performs variable expansion. Since perl 5.6, glob()
uses the File::Glob
module which does the work itself, without the shell, and doesn't expand environment variables (which glob was never intended to do). %ENV
is the proper way to get at the environment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With