Согласно документации Perl относительно файла globbing, оператора <*> или шарика () функция при использовании в скалярном контексте должна выполнить итерации через список файлов, соответствующих указанному шаблону, возвратив следующее имя файла каждый раз, когда это называют или undef, когда больше нет файлов.
Но, процесс итерации только, кажется, работает из цикла. Если это не находится в цикле, то это, кажется, запускается сразу, прежде чем все значения были считаны.
Из документов Perl:
В скалярном контексте шарик выполняет итерации посредством таких расширений имени файла, возвращаясь 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 files...file1.txt, file2.txt и file3.txt, вышеупомянутый код произведет:
file1.txt file1.txt file1.txt file1.txt file2.txt file3.txt
Примечание: Фактический сценарий жемчуга должен быть вне тестового каталога, или Вы будете видеть имя файла сценария в выводе также.
Я делаю что-то не так здесь или являюсь этим, как это, как предполагается, работает?
Вот способ передать магию состояния оператора <>
glob в объект, которым вы можете манипулировать обычным способом: анонимные подпрограммы (и / или замыкания)!
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 вместо:)
(Царапая свои ржавые воспоминания о Perl ...) Я думаю, что несколько лексических экземпляров <*>
рассматриваются как независимые вызовы glob, тогда как в цикле while вы вызываете то же самое «экземпляр» (что бы это ни значило).
Представьте, например, что если бы вы сделали это:
while (<*>) { ... }
...
while (<*>) { ... }
Вы, конечно, не ожидали бы, что эти два вызова будут мешать друг другу.
Следующий код, кажется, также создает два отдельных экземпляра итератора ...
for ( 1..3 ) { $filename = <*>; print "$filename\n" if defined $filename; $filename = <*>; print "$filename\n" if defined $filename; }
Думаю, я вижу здесь логику, но это противоречит документации и противоречит интуиции. В документации ничего не говорится о необходимости быть в цикле, чтобы итерация работала.
Также из perlop
:
(файл) glob оценивает свой (встроенный) аргумент только тогда, когда он начинает новый список .
Вызов glob
создает список, который либо возвращается целиком (в контексте списка), либо извлекается по одному элементу за раз (в скалярном контексте). Но каждый вызов glob
создает отдельный список.