根据关于文件globbing的Perl文档,< *> operator或glob()函数在标量上下文中使用时,应遍历匹配指定模式的文件列表,每次调用时返回下一个文件名,或者当没有更多文件时返回undef。
但是,迭代过程似乎只能在循环中起作用。如果它不在循环中,那么它似乎在读取所有值之前立即重新开始。
来自Perl文档:
在标量上下文中,glob遍历此类文件名扩展,在列表耗尽时返回undef。 的
http://perldoc.perl.org/functions/glob.html
但是,在标量上下文中,操作符在每次调用时返回下一个值,或者在列表用完时返回undef。 的
http://perldoc.perl.org/perlop.html#I/O-Operators
示例代码:
use warnings; use strict; my $filename; # in scalar context, <*> should return the next file name # each time it is called or undef when the list has run out $filename = <*>; print "$filename\n"; $filename = <*>; # doesn't work as documented, starts over and print "$filename\n"; # always returns the same file name $filename = <*>; print "$filename\n"; print "\n"; print "$filename\n" while $filename = <*>; # works in a loop, returns next file # each time it is called
在包含3个文件... file1.txt,file2.txt和file3.txt的目录中,上面的代码将输出:
file1.txt file1.txt file1.txt file1.txt file2.txt file3.txt
注意:实际的perl脚本应该位于测试目录之外,否则您也会在输出中看到脚本的文件名。 的
我在这里做错了什么,或者这是怎么回事?
答案 0 :(得分:9)
这是一种将<>
glob运算符状态的魔法捕获到一个对象中的方法,你可以用正常的方式操作它:anonymous subs(和/或closures)!
sub all_files {
return sub { scalar <*> };
}
my $iter = all_files();
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";
或者也许:
sub dir_iterator {
my $dir = shift;
return sub { scalar glob("$dir/*") };
}
my $iter = dir_iterator("/etc");
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";
然后我再次倾向于在“好奇心”下提出这个问题。忽略glob()
/ <>
的这种特殊怪异,并使用opendir
/ readdir
,IO::All / readdir
或File::Glob代替: )
答案 1 :(得分:5)
以下代码似乎也创建了2个独立的迭代器实例......
for ( 1..3 ) { $filename = <*>; print "$filename\n" if defined $filename; $filename = <*>; print "$filename\n" if defined $filename; }
我想我看到那里的逻辑,但它与文档有点反直觉和矛盾。文档没有提到必须处于循环中以使迭代工作的任何事情。
答案 2 :(得分:3)
同样来自perlop
:
(文件)glob仅在启动新列表时评估其(嵌入)参数。
调用glob
会创建一个列表,该列表要么全部返回(在列表上下文中),要么一次检索一个元素(在标量上下文中)。但每次调用glob
都会创建一个单独的列表。
答案 3 :(得分:0)
(抓住我对Perl的生锈记忆......)我认为<*>
的多个词法实例被视为glob的独立invokations,而在while循环中你调用相同的“实例”(无论那意味着什么)。
想象一下,例如,如果你这样做了:
while (<*>) { ... }
...
while (<*>) { ... }
你当然不希望这两次调用相互干扰。