在 grep 表达式中使用 chop

Using chop in grep expression

我的 Perl 脚本搜索文件名目录,使用 grep 只输出文件名,名称中没有数字 2-9。这意味着,按照预期,以数字“1”结尾的文件名也将被返回。但是,我想使用 chop 函数输出这些不带“1”的文件名,但不知道如何操作。也许 grepchop 函数可以组合在一行代码中来实现这一点?请指教。谢谢

这是我的 Perl 脚本:

#!/usr/bin/perl
use strict;
use warnings;

my $dir = '/Users/jdm/Desktop/xampp/htdocs/cnc/images/plants';
opendir(DIR, $dir);
@files = grep (/^[^2-9]*\.png\z/,readdir(DIR));

foreach $file (@files) {
   print "$file\n";
}

这是输出:

Ilex_verticillata.png
Asarum_canadense1.png
Ageratina_altissima.png
Lonicera_maackii.png
Chelone_obliqua1.png

这是我想要的输出,其中从文件名末尾删除了数字“1”:

Ilex_verticillata.png
Asarum_canadense.png
Ageratina_altissima.png
Lonicera_maackii.png
Chelone_obliqua.png

您可以使用以下内容:

s/1//g for @files;

也可以使用 map 将解决方案集成到您的链中。

my @files =
   map s/1//rg,
      grep /^[^2-9]*\.png\z/,
         readdir(DIR);

要删除的数字1在扩展名之前的名称末尾;这与完全过滤数字 (2-9) 不同,我不会尝试将其放入一个操作中。

相反,一旦您有了筛选列表(名称中没有 2-9),然后剪掉 1。看到所有感兴趣的名字都是 .png 可以简单地使用正则表达式

$filename =~ s/1\.png\z/.png/;

如果 .png 之前没有 1,则字符串不变。如果可能涉及其他扩展名,那么您应该使用模块来分解文件名。

要合并它,您可以通过 map

传递 grep 的输出
opendir my $dfh, $dir  or die "Can't open $dir: $!";

my @files = 
    map { s/1\.png\z/.png/r } 
    grep { /^[^2-9]*\.png\z/ } 
    readdir $dfh;

其中我还引入了词法目录文件句柄而不是 glob,并添加了检查 opendir 是否有效。需要 map 中替换的 /r 修饰符,以便返回字符串(如果正则表达式不匹配,则更改或不变),而不是就地更改,根据此处的需要。

不过,这会两次传递文件名列表,同时可以使用直接循环。原则上可能会影响性能;然而,这里的所有操作都是在列表的每个元素上完成的,因此性能差异很小。