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

Arrays 如何在perl中使用grep从一个数组到另一个数组选择元素?,arrays,perl,grep,text-processing,Arrays,Perl,Grep,Text Processing,我想了解CWD中的文件与@files中的文件之间的区别: 现在currect目录有以下文件: $ls a.txt e.txt getopt.html 使用此表达式push@files、foo.txt、bar.txt; 数组包含以下元素:foo.txt、bar.txt、a.txt、e.txt、getopt.html,这是正确的,但现在我只想选择那些不在CWD中的文件: @差分=grep{!/^\./和$i!=$\}readdir CWD;,所以我希望数组@difference会再次出现foo

我想了解CWD中的文件与@files中的文件之间的区别:

现在currect目录有以下文件:

$ls
a.txt  e.txt  getopt.html
使用此表达式push@files、foo.txt、bar.txt; 数组包含以下元素:foo.txt、bar.txt、a.txt、e.txt、getopt.html,这是正确的,但现在我只想选择那些不在CWD中的文件: @差分=grep{!/^\./和$i!=$\}readdir CWD;,所以我希望数组@difference会再次出现foo.txt,bar.txt,只有我现在觉得这没有意义,这只是一个例子。但是打印没有输出任何内容,有什么问题吗?

在同一个文件句柄上有两个readdir操作。一旦第一个到达EOF,就不再返回任何内容

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

在同一个文件句柄上有两个readdir操作。一旦第一个到达EOF,就不再返回任何内容


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

您的代码有很多问题:

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

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

循环的每次迭代都会擦除@differences的上一个值,因为您使用=。想必推动会更有意义

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

您应该检查opendir是否成功地添加了一个或多个。。。到opendir行。另外,请注意,openmy$CWD,getcwd相当于更简单的openmy$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;使用警告;根据剧本。始终将它们添加到代码中。在这种情况下,它不会帮助你找出问题所在,它会在未来为你节省无数的时间。另外,始终使用词法文件/目录句柄,即执行opendir my$CWD,dir而不是open CWD,dir。

您的代码有很多问题:

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

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

循环的每次迭代都会擦除@differences的上一个值,因为您使用=。想必推动会更有意义

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

您应该检查opendir是否成功地添加了一个或多个。。。到opendir行。另外,请注意,openmy$CWD,getcwd相当于更简单的openmy$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;使用警告;根据剧本。始终将它们添加到代码中。在这种情况下,它不会帮助你找出问题所在,它会在未来为你节省无数的时间。另外,请始终使用词法文件/目录句柄,也就是说,使用opendir my$CWD,dir而不是open CWD,dir。

正如您自己编写的那样,您的示例没有多大意义,这让我怀疑这是否是一个错误。考虑一下你想达到的目标,我们也许能给出更好的答案。你自己写的例子,你的例子没有什么意义,这让我怀疑这不是一个。考虑一下你想达到的目标,我们可以给出更好的答案。我只使用变量和大写句柄。它让我的代码更干净,为什么要把它们混在一起?@milanHrabos它不会让你的代码更干净。首先,在前面加一美元不需要任何费用。第二,如果您使用strict和a$犯了像CDW而不是CWD这样的拼写错误,Perl将在编译时发出错误。如果没有$,该行最终将失败,可能是无声的,并且您将很难调试它。第三,使用$$意味着变量是词汇范围的,这意味着在调用函数时不会有任何问题。例如,@ MalnHabROS,考虑子f{open FH,@milanHrabos变量范围应受到限制的想法,例如通过避免全局变量CWD而支持适当范围的变量my$CWD是计算机科学的基本原则
Enci仅对变量使用$,对句柄使用大写。它让我的代码更干净,为什么要把它们混在一起?@milanHrabos它不会让你的代码更干净。首先,在前面加一美元不需要任何费用。第二,如果您使用strict和a$犯了像CDW而不是CWD这样的拼写错误,Perl将在编译时发出错误。如果没有$,该行最终将失败,可能是无声的,并且您将很难调试它。第三,使用$$意味着变量是词汇范围的,这意味着在调用函数时不会有任何问题。例如,@ MalnHabROS,考虑子f{open FH,@milanHrabos变量的范围应该受到限制的想法,例如通过避免全局变量CWD而支持适当范围的变量my$CWD是计算机科学的一个基本原则