在perl中,有没有一种简洁的方法来组合glob和printf?

发布于 2024-10-10 10:57:01 字数 826 浏览 4 评论 0原文

我希望 @list 包含 $root_dir 中与 *YYYYMMDD* 匹配的所有文件名,其中 YYYYMMDD 是 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)>;

I want @list to contain all the filenames in $root_dir that match *YYYYMMDD*, where YYYYMMDD is 25 hours ago.

I try ...

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";
}

... but instead of getting a list of files, I get readline() on unopened filehandle.

I know the <> operator can interpret variables, so <$y$m$d> would work during two-thirds of the days during the last three months of the year because those would be months and days that have two digits, but that is not robust.

Do I have to write ...

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

... or is there something more concise? Something like ...

# 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)>;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

两个我 2024-10-17 10:57:01

使用

my @files = glob($pattern);

<...> 运算符已经太重载了。具体来说,<$...>被视为文件句柄。

Use

my @files = glob($pattern);

The <...> operator is way too overloaded already. Specifically, <$...> is taken as a filehandle.

妳是的陽光 2024-10-17 10:57:01

<> 可以表示 readlineglob,具体取决于它的使用方式。来自珀洛普:

如果尖括号包含的是一个简单的标量变量(例如,<$foo>),
那么该变量包含要输入的文件句柄的名称或其
typeglob,或对相同[...]的引用

如果尖括号内的内容既不是文件句柄也不是简单的标量
包含文件句柄名称、typeglob 或 typeglob 引用的变量,它是
解释为要通配的文件名模式 [...]

这种区别仅根据句法基础确定。 [强调我的]

由于 $pattern 是一个简单的标量,因此它被解释为作为句柄,Perl 尝试执行readline。直接调用 glob

my @files = glob($pattern);

<> 的重载可能会有点混乱。如果您认为这是一种有趣的编写 iterator->next 的方式,这可能会有所帮助。 (readlineglob 都像标量上下文中的迭代器一样。)

<> can mean either readline or glob depending on how it's used. From perlop:

If what the angle brackets contain is a simple scalar variable (e.g., <$foo>),
then that variable contains the name of the filehandle to input from, or its
typeglob, or a reference to the same [...]

If what's within the angle brackets is neither a filehandle nor a simple scalar
variable containing a filehandle name, typeglob, or typeglob reference, it is
interpreted as a filename pattern to be globbed [...]

This distinction is determined on syntactic grounds alone. [emphasis mine]

Since $pattern is a simple scalar it is interpreted as a handle and Perl attempts to do a readline. Call glob directly instead:

my @files = glob($pattern);

The overloading of <> can be a little confusing. It might help if you think of it as being a funny way of writing iterator->next. (Both readline and glob act like iterators in scalar context.)

江湖正好 2024-10-17 10:57:01

有点多余,你可以使用 CPAN 中的东西来代替所有这些恶作剧:

use File::Find::Rule;

my @files = File::Find::Rule->file->name( $pattern )->in( $root_dir );

A bit superfluous, instead of all those shenanigans, you could use something from CPAN instead:

use File::Find::Rule;

my @files = File::Find::Rule->file->name( $pattern )->in( $root_dir );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文