如何在perl中使用grep从一个数组中选择元素到另一个数组



我想捕获CWD中的文件和@files:中的文件之间的差异

#!/usr/bin/perl -w
use Cwd qw[getcwd abs_path];
opendir CWD, getcwd;
@files=grep{!/^./}readdir CWD;
push @files, ("foo.txt", "bar.txt");
for my $i (@files){
@difference=grep { !/^./ and $i!=$_ } readdir CWD;
}
print "$_n" for @differenc 

现在curect目录有以下文件:

$ls
a.txt  e.txt  getopt.html

用这个表达式push @files, ("foo.txt", "bar.txt");数组有以下元素:("foo.txt", "bar.txt", "a.txt", "e.txt", "getopt.html"),这是正确的,但现在我只想选择那些在CWD中是而不是的文件:@difference=grep { !/^./ and $i!=$_ } readdir CWD;,所以我希望数组@difference再次只有("foo.txt", "bar.txt")(我现在这没有意义,只是举个例子(。但是打印没有输出任何内容,这是怎么回事?

您的代码有很多问题:

  • 您的第二个readdir(在for my $i (@files)循环中(没有读取任何内容,因为第一个(@files=grep{!/^./}readdir CWD;(已经读取了整个目录。您可以先使用rewinddir,但简单地使用@files的副本(在推送foo.txtbar.txt之前(会更简单、更高效。

  • 您正在使用!=而不是ne来比较字符串。

  • 循环的每次迭代都会擦除@differences的上一个值,因为您使用=对其进行了赋值。大概push会更有意义。

  • 循环中的逻辑有点缺陷。grep返回满足条件的元素,但您更感兴趣的是是否有任何元素满足条件

  • 您应该检查opendir是否成功(通过在opendir行中添加or die ...(。此外,请注意,open my $CWD, getcwd等效于更简单的open my $CWD, "."

你可能想做的是:

use strict;
use warnings;
opendir my $CWD, "." or die "Could not open '.': $!";
my @files = grep{!/^./} readdir $CWD;
my @init_files = @files;
push @files, ("foo.txt", "bar.txt");
my @difference;
for my $i (@files){
push @difference, (grep { !/^./ and $i eq $_ } @init_files) ? () : $i;
}
print "$_n" for @difference

然而,这远不是有效的,而且它需要更复杂。我建议:

my %files = map { $_ => 1 } grep {!/^./} readdir $CWD;
my @difference;
for ("foo.txt", "bar.txt") {
push @difference, $_ if ! exists $files{$_};
}
print "$_n" for @difference

请注意,我已将use strict; use warnings;添加到脚本中。始终将它们添加到代码中。虽然在这种特定的情况下,它不会帮助你找出问题所在,但它会在未来为你节省无数的时间。此外,始终使用词法文件/目录句柄(即,使用opendir my $CWD, "dir"而不是open CWD, "dir"(。

在同一个文件句柄上有两个readdir操作。一旦第一个到达EOF,就没有什么可返回的了。

在第二次迭代之前添加`rewinddir操作。

相关内容

  • 没有找到相关文章

最新更新