File 打开目录并在文件中搜索模式
我的Perl脚本应该打开目录中的所有文件,搜索其中的模式,并打印包含该模式的整行。 下面是代码。代码无法打开该文件File 打开目录并在文件中搜索模式,file,perl,File,Perl,我的Perl脚本应该打开目录中的所有文件,搜索其中的模式,并打印包含该模式的整行。 下面是代码。代码无法打开该文件 my $dir = 'dir1/dir2'; opendir (DIR, $dir) or die $!; my @dir = readdir DIR; foreach my $item (@dir) { open(FILE, "<", "file.txt") or die "Can't open < file
my $dir = 'dir1/dir2';
opendir (DIR, $dir) or die $!;
my @dir = readdir DIR;
foreach my $item (@dir) {
open(FILE, "<", "file.txt")
or die "Can't open < file.txt: $!";
while($line= <FILE>) {
print "$line" if $line=~ /pattern/;
}
close FILE;
}
closedir DIR;
请建议一些方法使其工作。返回的只是名称file.txt,而不是路径而不是dir1/dir2/path.txt
因此,当程序试图打开$item†时,结果证明没有这样的事情-需要打开$dir/$item。或者,在文件列表中的每个条目前加上前缀,然后使用正确的路径
use warnings;
use strict;
my $dir = 'dir1/dir2';
opendir (my $dh, $dir) or die $!;
my @entries = map { "$dir/$_" } readdir $dh;
closedir $dh;
foreach my $item (@entries) {
next if not -f $item;
open(my $fh, "<", $item) or die "Can't open < $item: $!";
while(my $line = <$fh>) {
print $line if $line =~ /pattern/;
}
close $fh;
}
但是,如果您确实要提前获取整个文件列表,而不是一次读取和处理一个项目,那么您最好立即根据需要对其进行过滤,因此
my @files = grep { -f } glob $dir;
您现在只有常规文件
当然,整个列表也可以在上面的程序中过滤。可以在地图上自己做
在这里,map还通过一个小技巧起到了过滤器的作用:当条目不是普通文件时返回的空列表在返回的列表中变平,从而有效地消失,因此在这种情况下等于不返回任何内容。或者,像往常一样将grep链接到map
这确实使列表又一次被忽略了,但这是优化的,而且几乎不会成为一个问题,除非我们有巨大的文件列表——这本身就带来了问题——而且我们经常这样做
我还想提到的是,也有一些很好的模块
举个例子
这是一个懒惰的迭代器。有关本模块提供的许多其他内容,请参阅文档等
†返回的不是file.txt,而是名称file.txt,而不是路径dir1/dir2/path.txt
因此,当程序试图打开$item†时,结果证明没有这样的事情-需要打开$dir/$item。或者,在文件列表中的每个条目前加上前缀,然后使用正确的路径
use warnings;
use strict;
my $dir = 'dir1/dir2';
opendir (my $dh, $dir) or die $!;
my @entries = map { "$dir/$_" } readdir $dh;
closedir $dh;
foreach my $item (@entries) {
next if not -f $item;
open(my $fh, "<", $item) or die "Can't open < $item: $!";
while(my $line = <$fh>) {
print $line if $line =~ /pattern/;
}
close $fh;
}
但是,如果您确实要提前获取整个文件列表,而不是一次读取和处理一个项目,那么您最好立即根据需要对其进行过滤,因此
my @files = grep { -f } glob $dir;
您现在只有常规文件
当然,整个列表也可以在上面的程序中过滤。可以在地图上自己做
在这里,map还通过一个小技巧起到了过滤器的作用:当条目不是普通文件时返回的空列表在返回的列表中变平,从而有效地消失,因此在这种情况下等于不返回任何内容。或者,像往常一样将grep链接到map
这确实使列表又一次被忽略了,但这是优化的,而且几乎不会成为一个问题,除非我们有巨大的文件列表——这本身就带来了问题——而且我们经常这样做
我还想提到的是,也有一些很好的模块
举个例子
这是一个懒惰的迭代器。有关本模块提供的许多其他内容,请参阅文档等
†而不是该文件.txt只返回名称,而不是路径。因此,当您尝试打开file.txt时,没有这样的事情-您需要说$dir/file.txt。另一种方法是在整个列表前面加上前缀,因此my@dir=map{$dir/$\uj}readdir-dir;现在@dir中的文件具有正确的路径hmm,如果按照您的逻辑,您尝试读取每个dir中的file.txt,但不是目录中的每个文件。您的描述与代码的逻辑不匹配。我不确定perl脚本是否是解决任务的强制要求。否则,您可以使用find和grep获得相同的结果find/some/dir-exec grep[pattern]{}-ls。此命令将搜索目录和子目录中的每个文件。@PolarBear也可以这样做,但不需要查找,因为grep有方法指定要搜索的内容,这里它很简单,grep[options]模式dir1/dir2/*其中选项将决定如何显示查找只需注意:并非所有版本的grep都支持子目录中的递归搜索-find/grep工作了很长时间,从未失败过。返回的只是名称,而不是路径。因此,当您尝试打开file.txt时,没有这样的事情-您需要说$dir/file.txt。另一种方法是在整个列表前面加上前缀,因此my@dir=map{$dir/$\uj}readdir-dir;现在@dir中的文件具有正确的路径hmm,如果按照您的逻辑,您尝试读取每个dir中的file.txt,但不是目录中的每个文件。您的描述与代码的逻辑不匹配。我不确定perl脚本是否是解决任务的强制要求。否则,您可以使用find和grep获得相同的结果find/some/dir-exec grep[pattern]{}-ls。此命令将搜索目录和子目录中的每个文件。@PolarBear也可以这样做,但不需要查找,因为grep有方法指定要搜索的内容,这里它很简单,grep[options]模式dir1/dir2/*其中选项将决定如何显示查找只需注意:并非所有版本的grep都支持subdir中的递归搜索 ectories-find/grep工作了很长时间,从未失败过。
my @files = grep { -f } map { "$dir/$_" } readdir $dh;
use Path::Tiny;
my $it = path($dir)->iterator;
while (my $entry = $it->()) {
# it omits . and ..
}