【问题标题】:Perl glob returning a false positivePerl glob 返回误报
【发布时间】:2015-01-11 06:31:32
【问题描述】:

看似简单的一段代码肯定没有按照我的意愿去做。

有人可以向我解释它的作用和原因吗?

my $dir = './some/directory';

if ( -d $dir && <$dir/*> ) {
    print "Dir exists and has non-hidden files in it\n";
}
else {
    print "Dir either does not exist or has no non-hidden files in it\n";
}

在我的测试用例中,该目录确实存在并且它是空的。但是,ifthen(第一个)部分触发了,而不是预期的 else 部分。

我不需要任何人建议如何完成我想要完成的事情。我只是想了解一下 Perl 对这段代码的解释,这绝对不符合我的。

【问题讨论】:

  • 你真的应该看看&lt;$dir/*&gt;返回的你认为不存在的东西。
  • 我做到了!我用join( ', ', &lt;$dir/*&gt; ) 或类似的东西打印它,它返回了我认为的结果。这也是我真正糊涂的原因之一。 @ysth 下面的回答似乎解开了这个谜。
  • @ysth 所说的意味着您正在此代码片段之外更改 $dir。对吗?
  • @borodin:我不这么认为。他说,在第一次调用时,它会返回第一个文件,第二次,第二次,直到它返回所有文件,即使在程序的不相关部分中使用也是如此。 $dir 可能会或可能不会改变,这没有区别。 Perl 在其他地方也有这个非常奇怪的习惯,我刚记得:upon2020.com/banter/2014/10/08/perl-really
  • 但是如果没有匹配./some/directory/*的文件或目录,那么glob应该在标量上下文中返回undef,在列表上下文中返回一个空列表:没有第一个文件。我已经运行了所有我能想到的测试,我无法复制你的例子。我知道each,但到目前为止我所读到的内容都无法解释您所描述的内容。

标签: perl glob


【解决方案1】:

在标量上下文中使用glob(又名&lt;filepattern&gt;)使其成为迭代器;每次调用它都会一次返回一个文件,并且在完成对初始结果的迭代之前不会响应模式的变化(例如,不同的 $dir);我怀疑这会导致您看到的问题。

简单的答案是始终在列表上下文中使用它,如下所示:

if( -d $dir && ( () = <$dir/*> ) ) {

glob 只能在标量上下文中安全地使用,如果你绝对确定你会在尝试开始新的迭代之前耗尽迭代器,那么你将执行多次。大多数情况下,完全避免在标量上下文中使用 glob 会更容易。

【讨论】:

  • scalar(&lt;$dir/*&gt;) 呢?
  • scalar 只是给出了它的操作数标量上下文,它在原始代码中已经有了。
  • 我实际上为此尝试了scalar(&lt;$dir/*&gt;),但显然这还不够好。
  • @ysth:我不关注。为什么scalar glob './empty_dir/*' 不返回undef?您是否建议实际代码在调用 glob 之间修改 $dir
  • @Borodin:如果是这样,肯定有问题;如果没有,还是有问题,因为scalar glob './not_empty_dir/*'在第一次之后偶尔会返回undef
【解决方案2】:

我相信@ysth 是正确的,但在标量上下文中重复调用glob不会产生误报。

例如

use strict;
use warnings;
use 5.010;

say scalar glob('/usr/*'), "\n";

say scalar glob('/usr/*'), "\n";

输出

/usr/bin

/usr/bin

是真的,glob 的任何单个调用 都会保持一个状态,所以如果我有

use strict;
use warnings;
use 5.010;

for my $dir ( '/sys', '/usr', '/sys', '/usr' ) {
  say scalar glob("$dir/*"), "\n";
}

输出

/sys/block

/sys/bus

/sys/class

/sys/dev

很明显,循环内的glob 语句保持状态,并忽略对$dir 的更改。

这类似于pos(和相应的\G 正则表达式锚)具有每个标量变量的状态,以及在没有特定文件句柄的情况下print 如何打印到最后选择 em>句柄。最后,这就是所有 Perl 的工作方式,it 变量 $_ 是终极示例。

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 2014-07-01
    • 2010-11-19
    • 1970-01-01
    • 2011-06-19
    • 2011-05-30
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多