В Perl, есть ли краткий способ объединить glob и printf? - PullRequest
0 голосов
/ 05 января 2011

Я хочу, чтобы @list содержал все имена файлов в $ root_dir, которые соответствуют * ГГГГММДД *, где ГГГГММДД - 25 часов назад.

Я пытаюсь ...

my ($y, $m, $d) = (localtime(time - 25 * 60 * 60))[5,4,3]; 
my $pattern = sprintf('*%4d%02d%02d*',$y+1900,$m+1,$d);
print "The pattern is $pattern\n"; 
my @files = <$pattern>;
foreach (@files) {
    print "$_\n";
}

... но вместо получения списка файлов я получаю readline () для неоткрытого дескриптора файла .

Я знаю, что оператор <> может интерпретировать переменные, поэтому <$ y $ m $ d> будет работать в течение двух третей дней в течение последних трех месяцев года, потому что это будут месяцы и дни, имеющие две цифры , но это не надежно.

Должен ли я написать ...

$m = sprintf('%02d',$m+1);  
$d = sprintf('%02d',$d+1);
my @files = <*$y$m$d*>;

... или есть что-то более краткое? Что-то вроде ...

# invalid code unless you want to produce the string "readline() on unopened filehandle" for some reason
my @files = <sprintf('*%4d%02d%02d*',$y+1900,$m+1,$d)>;

Ответы [ 3 ]

7 голосов
/ 05 января 2011

Использование

my @files = glob($pattern);

Оператор <...> слишком перегружен.В частности, <$...> берется как дескриптор файла.

4 голосов
/ 05 января 2011

<> может означать либо readline, либо glob в зависимости от того, как он используется. Из perlop:

Если то, что содержат угловые скобки, является простой скалярной переменной (например, <$foo>), затем эта переменная содержит имя дескриптора файла для ввода или его typeglob, или ссылка на тот же [...]

Если то, что находится в угловых скобках, не является ни файловым дескриптором, ни простым скаляром переменная, содержащая имя дескриптора файла, ссылку на typeglob или typeglob, интерпретируется как шаблон имени файла, который будет выделен [...]

Это различие определяется только по синтаксическим признакам. [выделено мной]

Поскольку $pattern - простой скаляр, он интерпретируется как дескриптор, и Perl пытается сделать readline. Позвоните glob напрямую вместо:

my @files = glob($pattern);

Перегрузка <> может немного сбивать с толку. Это может помочь, если вы думаете, что это забавный способ написания iterator->next. (И readline, и glob действуют как итераторы в скалярном контексте.)

3 голосов
/ 05 января 2011

Немного излишне, вместо всех этих махинаций, вы можете вместо этого использовать что-то из CPAN:

use File::Find::Rule;

my @files = File::Find::Rule->file->name( $pattern )->in( $root_dir );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...