6

我不一定要寻找更好的方法来做到这一点,而是非常感谢对输出的解释。最近,一位资深程序员问我为什么他的代码有效,但只是一个例子。我发现它每隔一段时间都有效。这是我的例子:

#!/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链接进行操作,但仍然找不到任何可以解释输出的内容。任何帮助将非常感激。

4

3 回答 3

13

glob在标量上下文中:

在标量上下文中,glob 遍历此类文件名扩展,当列表用完时返回 undef。

foreach (@list_env_vars){
    print "$_ = ".glob()."\n";
}

glob()真的有glob($_)。每次迭代,都$_包含字符串$SERVER。鉴于环境变量没有改变,$SERVER扩展为相同的字符串。第一次,这个字符串被返回。接下来,列表已用尽,因此undef返回。第三次,我们重新开始。...

澄清:第二次调用的参数与第一次调用的参数相同并不重要,因为无法重置glob的迭代器。

您可以使用以下示例更清楚地看到这一点(当前目录包含文件 '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:\温度> 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)};
于 2009-08-13T21:39:04.933 回答
4

顺便说一句,在 5.004 中你得到一个变量扩展,而在 5.10 中你只是得到你的文字字符串,是因为在旧的 perl 上,glob()是由系统 shell 执行的,这就像执行变量扩展的副作用一样。从 perl 5.6 开始,glob()使用File::Glob本身完成工作的模块,没有外壳,并且不扩展环境变量(glob 从未打算这样做)。%ENV是获取环境的正确方法。

于 2009-08-14T21:50:40.240 回答
0

关于旧行为的注释,wiki'd 为了您的方便(这样我就有了完整的标记范围并且没有 500 个字符的限制):

glob在 5.6中更改的事实在 docs ( , , )<*globbything*>中被提及,但关于它曾经如何工作的唯一真正来源是 .5.6 之前的版本。这是 5.005 中的相关位:perl56deltaperlop-f globperlop

例子:

while (<*.c>) {
    chmod 0644, $_;
}

相当于

open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
    chop;
    chmod 0644, $_;
}

事实上,它目前就是这样实现的。(这意味着除非您的机器上有 csh(1),否则它不适用于包含空格的文件名。)

呵呵,真是恶毒的东西。无论如何,如果您发现自己想像那样查阅旧的 perldocs,只需转到 search.cpan.org,拉出perl发行版,使用下拉列表选择旧版本,然后单击进入您需要的文档。perl本身并不会真正从 CPAN 中“整理”出来;目前从 5.004 开始的所有内容都可以在不点击 BackPan 的情况下使用。

于 2009-08-22T06:59:25.643 回答