我不一定会寻找更好的方法来做到这一点,而是对输出的解释将非常感激。最近,一位资深程序员问我为什么他的代码有效,但仅限于一个实例。我发现的是它每隔一段时间都有效。这是我的例子:
#!/usr/bin/perl -w
use strict;
my @list_env_vars = (
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
'$SERVER',
);
foreach (@list_env_vars){
print "$_ = ".glob()."\n";
}
perl 5.004的输出:
$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =
或输出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 =
我个人从未以这种方式使用过glob(),所以我没有能力回答他。我阅读了perldoc glob文档,并按照该页面上的File::Glob链接进行操作,但仍找不到任何可以解释输出的内容。任何帮助将不胜感激。
答案 0 :(得分:13)
glob
:
在标量上下文中,glob遍历这样的文件名扩展,当列表用完时返回undef。
在
foreach (@list_env_vars){
print "$_ = ".glob()."\n";
}
glob()
确实存在glob($_)
。每次迭代,$_
都包含字符串$SERVER
。鉴于环境变量未发生变化,$SERVER
将扩展为相同的字符串。第一次,返回此字符串。接下来,列表已用尽,因此返回undef
。第三次,我们重新开始。 ...
澄清:第二次调用的参数与第一次调用的参数相同并不重要,因为无法重置glob
的迭代器。 / p>
使用以下示例可以更清楚地看到这一点(当前目录包含文件'1.a',1.b','2.a'和'2.b'):
#!/usr/bin/perl -w
use strict;
my @patterns = (
'*.a',
'*.b',
);
for my $v ( @patterns ) {
print "$v = ", scalar glob($v), "\n";
}
输出:
C:\Temp> d *.a = 1.a *.b = 2.a
我建议通过%ENV
哈希来访问环境变量:
my @list_env_vars = ($ENV{SERVER}) x 6;
或
my @list_env_vars = @ENV{qw(HOME TEMP SERVER)};
答案 1 :(得分:4)
顺便提一下,为什么在5.004你得到一个变量扩展,而在5.10你只是得到你的文字字符串,是因为在旧的perl上,glob()
是由系统shell执行的,就像一个副作用执行变量扩展。从perl 5.6开始,glob()
使用File::Glob
模块来完成工作本身,没有shell,并且不扩展环境变量(glob从未打算这样做)。 %ENV
是了解环境的正确方法。
答案 2 :(得分:0)
关于旧行为的注释,wiki为了您的方便(以及我有完整的标记范围,没有500-char限制):
在文档(glob
,<*globbything*>
,perl56delta
)中提到了perlop
和-f glob
在5.6中发生更改的事实,但唯一真实的关于它以前的工作原理的来源是perlop
的5.6之前的版本。这是5.005的相关位:
嘿,那是非常邪恶的东西。无论如何,如果你发现自己想要查询这样的旧perldocs,只需转到search.cpan.org,调出示例:
while (<*.c>) { chmod 0644, $_; }
相当于
open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|"); while (<FOO>) { chop; chmod 0644, $_; }
事实上,它目前以这种方式实施。 (这意味着除非您的计算机上有csh(1),否则它不会对包含空格的文件名起作用。)
perl
发行版,使用下拉列表选择旧版本,然后点击进入doc你需要的。 perl
本身并不真正受到CPAN的“整理”;目前从5.004开始的所有内容都可以使用而无需点击BackPan。