仍然遇到perl编程问题,我需要推动使脚本运行起来。 我有两个文件,我想使用列表文件从数据中“提取”行。问题是列表文件的格式如下:
X1 A B
X2 C D
X3 E F
我的数据如下:
A X1 2 5
B X1 3 7
C X2 1 4
D X2 1 5
我需要从列表文件中获取元素对,通过这些元素对选择数据文件中的行。同时我想写一个这样的输出:
X1 A B 2 5 3 7
X2 C D 1 4 1 5
我正在尝试编写perl代码,但我无法生成有用的东西。我在这一点上:
open (LIST, "< $fils_list") || die "impossibile open the list";
@list = <LIST>;
close (LIST);
open (HAN, "< $data") || die "Impossible open data";
@r = <HAN>;
close (HAN);
for ($p=0; $p<=$#list; $p++){
chomp ($list[$p]);
($x, $id1, $id2) = split (/\t/, $list[$p]);
$pair_one = $id1."\t".$x;
$pair_two = $id2."\t".$x;
for ($i=0; $i<=$#r; $i++){
chomp ($r[$i]);
($a, $b, $value1, $value2) = split (/\t/, $r[$i]);
$bench = $a."\t".$b;
if (($pair_one eq $bench) || ($pair_two eq $bench)){
print "I don't know what does this script must print!\n";
}
}
}
我无法理解要打印的内容。 任何建议都是非常受欢迎的!
答案 0 :(得分:2)
一些一般性建议:
$a
或$value1
(如果我在下面这样做,这是由于我缺乏域知识)。use strict; use warnings;
。use autodie
用于自动错误处理。此外,请使用open
这样的open my $fh, "<", $filename
函数,因为这样更安全。
还记得我对数据结构的看法吗?在第二个文件中,您有
之类的条目A X1 2 5
这看起来像辅助密钥,主键和一些数据列。键值关系最好通过哈希表表示。
use strict; use warnings; use autodie;
use feature 'say'; # available since 5.010
open my $data_fh, "<", $data;
my %data;
while (<$data_fh>) {
chomp; # remove newlines
my ($id2, $id1, @data) = split /\t/;
$data{$id1}{$id2} = \@data;
}
现在%data
是一个嵌套哈希,我们可以使用它来轻松查找:
open my $list_fh, "<", $fils_list;
LINE: while(<$list_fh>) {
chomp;
my ($id1, @id2s) = split /\t/;
my $data_id1 = $data{$id1};
defined $data_id1 or next LINE; # maybe there isn't anything here. Then skip
my @values = map @{ $data_id1->{$_} }, @id2s; # map the 2nd level ids to their values and flatten the list
# now print everything out:
say join "\t", $id1, @id2s, @values;
}
map
函数有点像foreach循环,并构建值列表。我们在这里需要@{ ... }
,因为数据结构不包含数组,而是对数组的引用。 @{ ... }
是解除引用运算符。
答案 1 :(得分:1)
我会这样做,主要是使用Hashes resp。散列和数组引用(test1.txt和test2.txt包含您在示例中提供的数据):
use strict;
use warnings;
open(my $f1, '<','test1.txt') or die "Cannot open file1: $!\n";
open(my $f2, '<','test2.txt') or die "Cannot open file2: $!\n";
my @data1 = <$f1>;
my @data2 = <$f2>;
close($f1);
close($f2);
chomp @data1;
chomp @data2;
my %result;
foreach my $line1 (@data1) {
my @fields1 = split(' ',$line1);
$result{$fields1[0]}->{$fields1[1]} = [];
$result{$fields1[0]}->{$fields1[2]} = [];
}
foreach my $line2 (@data2){
my @fields2 = split(' ',$line2);
push @{$result{$fields2[1]}->{$fields2[0]}}, $fields2[2];
push @{$result{$fields2[1]}->{$fields2[0]}}, $fields2[3];
}
foreach my $res (sort keys %result){
foreach (sort keys %{$result{$res}}){
print $res . " " . $_ . " " . join (" ", sort @{$result{$res}->{$_}}) . "\n";
}
}