在文件夹中循环读取具有特定模式的文件…获取错误perl
我有一个代码,可以读取两个文件作为输入,并在输出中的两个写入匹配元素之间进行比较。让我们将脚本中的$ListScript文件看作是用于从$DATAX文件中选择元素的固定列表。我试图让这个脚本在一个文件夹中循环并读取多个具有特定名称模式的数据文件,但是我遇到了一个错误,我无法解决它 这是我的名为“list.txt”的列表文件: 我的第一个数据文件名为“data\u file1.txt”: 我的第二个数据文件名为“data\u file2.txt”: 我希望获得如下输出:在文件夹中循环读取具有特定模式的文件…获取错误perl,perl,Perl,我有一个代码,可以读取两个文件作为输入,并在输出中的两个写入匹配元素之间进行比较。让我们将脚本中的$ListScript文件看作是用于从$DATAX文件中选择元素的固定列表。我试图让这个脚本在一个文件夹中循环并读取多个具有特定名称模式的数据文件,但是我遇到了一个错误,我无法解决它 这是我的名为“list.txt”的列表文件: 我的第一个数据文件名为“data\u file1.txt”: 我的第二个数据文件名为“data\u file2.txt”: 我希望获得如下输出: X1 A B 2 5 3
X1 A B 2 5 3 7
X2 C D 1 4 1 5
X3 E F 5 7 3 4
我的两个数据文件都在一个包含其他文件的文件夹中,因此我需要将“数据”匹配为模式,以识别正确的输入
这是我的代码:
my $list_file = "list.txt";
my $dirname = "data_directory";
my $dh;
use strict;
use warnings;
use autodie;
use feature 'say';
opendir ($dh, $dirname) || die "Impossible open the $dirname!";
while (my $data_file = readdir ($dh)){
if ("$dh/$data_file" =~ /data/){
open my $data_fh, "<", $data_file;
my %data;
while (<$data_fh>) {
chomp;
my ($id2, $id1, @data) = split /\t/;
$data{$id1}{$id2} = \@data;
}
open my $list_fh, "<", $list_file;
LINE: while(<$list_fh>) {
chomp;
my ($id1, @id2s) = split /\t/;
my $data_id1 = $data{$id1};
defined $data_id1 or next LINE;
my @values = map @{ $data_id1->{$_} }, @id2s;
say join "\t", $id1, @id2s, @values;
}
}
}
closedir (DIR);
欢迎提出建议 首先需要定义什么是
$fils\u list
$ perl -cw ff.pl
Global symbol "$fils_list" requires explicit package name at ff.pl line 22.
ff.pl had compilation errors.
与此相反:-
open my $data_fh, "<", $data_file;
打开我的$data\u fh,“如果您要查找所有文件的列表,这些文件的名称以data\uu
开头,以.txt
结尾,并且它们保证位于脚本工作目录正下方的目录树的单个级别中,您可以使用
@data_files = glob('**/data_*.txt');
如果它们位于单个目录中,例如“datapath”,则更简单;只需
@data_files = glob('datapath/data_*.txt');
一般来说,这是一个您不必自己解决的问题,因为Perl实现者已经为您解决了这个问题;有关如何适应glob()的更多信息,请参阅
对于您的具体情况,请尝试使用perldoc-f glob
,这将为您提供所有您可以接受的详细信息。如果失败,您可以查看文件::Find
,这需要更多的努力,但在交换方面提供了更大的灵活性;对于问题glob()
无法解决,File::Find
可能是您要使用的第一个工具
但是,在本例中,假设以下目录结构
list-and-data/
list-and-data/list.txt
list-and-data/data/data_1.txt
list-and-data/data/data_2.txt
list-and-data/data/et-cetera.txt
list-and-data/data/something-else.txt
如果您只想在data/
中选择数据文件,您可以简单地:
sub read_file {
my $filename = shift();
my @data;
open my $fh, '<', $filename
or die "Can't open '$filename' to read: $!\n";
@data = <$fh>
or die "Failed to read '$filename', or empty: $!\n";
close $fh;
chomp foreach @data;
return \@data;
};
my $list_file = "list.txt";
my $dirname = "data/";
my $data_filespec = "data_*.txt";
my @list = @{ read_file($list_file) };
my %data = {};
my @files = glob("$dirname/$data_filespec");
foreach my $file (@files) {
my $basename = $file; $basename =~ s@^.*/@@;
$data{$basename} = read_file($file);
};
子读取文件{
我的$filename=shift();
我的@数据;
打开我的$fh,'如果我的数据文件有数百个,该怎么办?@Gabelins检查更新,第二个参数获取文件夹中所有匹配*data*.txt
模式的文件。我已经多年没有看到有人用Perl编写如此流利的awk了。这对我们这些天生爱唠叨的人是一个有益的教训——我向您致敬,先生。@AaronMiller谢谢;c不过,我不能对awk发表评论,因为我对ITI不太熟悉。如果我在打开目录后添加glob()命令,我会出现以下错误:“无法在code.pl行打开'glob(0x1198cd8)/data_file1.txt'读取:'没有这样的文件或目录'23@Gabelinsglob()
不在目录句柄上操作;您给它一个路径规范,它会返回一个与规范匹配的扩展路径列表。它实际上与shell globbing非常相似,因此得名;我鼓励您仔细阅读perldoc-f glob
以了解它的工作原理以及它能为您做些什么。同时,我将我的问题倾向于包括一个简单的例子。在“$dh/$data\u file”
中,$dh
不是路径。而且,打开…$data\u file
可能不会指向文件,因为您需要一个更完整的路径,如“$dirname/$data\u file”
。
open my $data_fh, "<", "$dh/$data_file"
@data_files = glob('**/data_*.txt');
@data_files = glob('datapath/data_*.txt');
list-and-data/
list-and-data/list.txt
list-and-data/data/data_1.txt
list-and-data/data/data_2.txt
list-and-data/data/et-cetera.txt
list-and-data/data/something-else.txt
sub read_file {
my $filename = shift();
my @data;
open my $fh, '<', $filename
or die "Can't open '$filename' to read: $!\n";
@data = <$fh>
or die "Failed to read '$filename', or empty: $!\n";
close $fh;
chomp foreach @data;
return \@data;
};
my $list_file = "list.txt";
my $dirname = "data/";
my $data_filespec = "data_*.txt";
my @list = @{ read_file($list_file) };
my %data = {};
my @files = glob("$dirname/$data_filespec");
foreach my $file (@files) {
my $basename = $file; $basename =~ s@^.*/@@;
$data{$basename} = read_file($file);
};
perl -ane '
BEGIN{ open $I,shift or die $! }
($x, $y) = splice(@F,0,2);
$h{$x}{$y} = "@F";
END{
@F=split,
s/$/ $h{ $F[1] }{ $F[0] } $h{ $F[2] }{ $F[0] }/,
print
while <$I>
}
' list.txt *data*.txt
X1 A B 2 5 3 7
X2 C D 1 4 1 5
X3 E F 5 7 3 4