Regex 使用perl grep排除文件

Regex 使用perl grep排除文件,regex,perl,grep,Regex,Perl,Grep,我想检查目录中的所有文件,除了以“.py”结尾的文件。 现有脚本中的行是: my @files = sort(grep(!/^(\.|\.\.)$/, readdir($dir_h))); 我想要像这样的东西: my @files = sort(grep(!/^(\.|\.\.|"*.py")$/, readdir($dir_h))); 您能帮我解释一下确切的语法吗?检查目录项是否为文件,然后排除以.py结尾的目录项: #!/usr/bin/env perl use warnings; us

我想检查目录中的所有文件,除了以“.py”结尾的文件。 现有脚本中的行是:

my @files = sort(grep(!/^(\.|\.\.)$/, readdir($dir_h)));
我想要像这样的东西:

my @files = sort(grep(!/^(\.|\.\.|"*.py")$/, readdir($dir_h)));

您能帮我解释一下确切的语法吗?

检查目录项是否为
文件
,然后排除以
.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);
使用正则表达式,而不是globs(也称为通配符)。正确的语法是

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$/

i、 e.点一次或两次,周围没有任何东西,或者最后是
.py

perl的内置
grep
实际上非常聪明-它迭代数组,依次对每个元素应用条件。它将每个元素设置为
$\u

这个条件可以是一个简单的正则表达式,但不一定是

因此,您可以-例如:

my @files = grep { -f $_ } readir(DIR); 
但是,由于
-f
默认为
$\u
,您还可以:

my @files = grep { -f } readdir (DIR); 
您还可以将正则表达式应用于
$\uu

my @files = grep { not m/\.py$/ } readdir (DIR); 
(注意-这与
而不是$\u=~ m/\.py$/
相同-默认情况下,模式适用于
$\u

因此,您可以通过以下方式做您想做的事情:

my @files = sort grep { not m/\.py$/ and -f } readdir (DIR);
尽管注意-这将在当前工作目录中工作,而不是用于读取单独的路径。您可以对不同的目录使用
readdir
,但我个人更喜欢
glob
——因为它也会填充路径:

my @files = sort grep { not m/\.py$/ and -f } glob ( "$dir/*" );