【发布时间】:2015-09-21 08:19:57
【问题描述】:
我想查看目录中的所有文件,以“.py”结尾的文件除外。 现有脚本中的行是:
my @files = sort(grep(!/^(\.|\.\.)$/, readdir($dir_h)));
我想要类似的东西:
my @files = sort(grep(!/^(\.|\.\.|"*.py")$/, readdir($dir_h)));
你能帮忙看看确切的语法吗?
【问题讨论】:
我想查看目录中的所有文件,以“.py”结尾的文件除外。 现有脚本中的行是:
my @files = sort(grep(!/^(\.|\.\.)$/, readdir($dir_h)));
我想要类似的东西:
my @files = sort(grep(!/^(\.|\.\.|"*.py")$/, readdir($dir_h)));
你能帮忙看看确切的语法吗?
【问题讨论】:
grep 使用正则表达式,而不是 glob(又名通配符)。正确的语法是
my @files = sort(grep(!/^(\.|\.\.|.*\.py)$/, readdir($dir_h)));
或者,没有不必要的括号
my @files = sort grep ! /^(\.|\.\.|.*\.py)$/, readdir $dir_h;
由于正则表达式中的括号不用于捕获,而仅用于优先级,您可以将它们更改为非捕获:
my @files = sort grep ! /^(?:\.|\.\.|.*\.py)$/, readdir $dir_h;
你可以用许多不同的方式表达相同的意思,例如
/^\.{1,2}$|\.py$/
即点一次或两次,周围什么都没有,或者.py在最后。
【讨论】:
perl 在grep 中的构建实际上非常聪明——它迭代一个数组,依次对每个元素应用一个条件。它将每个元素设置为$_。
这个条件可以是一个简单的正则表达式,但不是必须的。
所以你可以 - 例如:
my @files = grep { -f $_ } readir(DIR);
但是因为-f 默认为$_,你也可以:
my @files = grep { -f } readdir (DIR);
您还可以将正则表达式应用于$_
my @files = grep { not m/\.py$/ } readdir (DIR);
(注意 - 这与 not $_ =~ m/\.py$/ 相同 - 默认情况下,模式适用于 $_)。
所以你可以做你想做的事:
my @files = sort grep { not m/\.py$/ and -f } readdir (DIR);
虽然注意 - 这将在当前工作目录中工作,而不是用于读取单独的路径。您可以将readdir 用于不同的目录,但我个人更喜欢glob - 因为它也填充了路径:
my @files = sort grep { not m/\.py$/ and -f } glob ( "$dir/*" );
【讨论】:
检查目录条目是否为files,然后排除那些以.py 结尾的条目:
#!/usr/bin/env perl
use warnings;
use strict;
my $dir = "/home/me/somedir";
# good examples in the perldoc:
# perldoc -f readdir
opendir(my $DIR, $dir) || die "Unable to open $dir : $!";
# -f checks that it is a plain file ( perldoc perlfunc )
# !~ means does not match ( perldoc perlre )
# m|\.py$| means a match string that ends in '.py'
my @files = sort grep { -f "$dir/$_" && $_ !~ m|\.py$| } readdir($DIR);
【讨论】: