是否可以使用两个键和值来合并多个文件?

问题描述 投票:2回答:1

我尝试合并3个文件 文件1:4列制表符分隔文件

ID   Column_1    Column_2     Column_3    
 A     100       100001         X   
 B     100        99999         Y     
 C     100        88888         Z    
 D      99       100001         Y   
 E      99        88888         Z       

文件2:3列制表符分隔文件

  Column_4    Column_5     Column_6    
  100       100001         X   
  100        99999         Y     
  100        88888         Z    
   99       100001         Y   
   99        88888         Z 

文件3:4列制表符分隔文件

 Column_7    Column_8     Column_9   Column_10   
    100       120000        100       100001
    100        66666        100        99999
    100        77777        100        88888
     99        100000        99       100001
     99        44444         99        88888  

我想制作一个合并文件

 ID  Column_1   Column_2   Column_3  Column_6  Column_7  Column_8  
 A     100       100001         X       X       100       120000 
 B     100        99999         Y       Y       100        66666
 C     100        88888         Z       Z       100        77777
 D      99       100001         Y       Y        99       100000   
 E      99        88888         Z       Z        99        44444  

我尝试使用哈希方法,取决于第1列和第2列。但我发现我有两个键和许多值。如何使用哈希来解析这些文件?

perl hash
1个回答
2
投票

您使用哈希是在正确的路径上,您只需要从每个表的列计算密钥。解决方案的部分:

  • 使用Text::CSV从3个TSV文件中读取每一行 对于每一行,调用特定于表的代码ref 提取密钥所需的2列,并将它们连接到密钥字符串$key 对于第一个表:在数组@order中保存键,即它定义输出表的顺序 在密钥%table下的哈希$key中:将从此表到最终表的列推送到数组引用
  • 循环在@order 从hash $key获取%table下的数组ref 使用Text::CSVSTDOUT将行转换为TSV
#!/usr/bin/perl
use warnings;
use strict;
use autodie;

use Text::CSV;

my $csv = Text::CSV->new({
    binary   => 1,
    eol      => "\n",
    sep_char => "\t",
}) or die "CSV creation\n";

sub read_file($$) {
    my($file, $code) = @_;
    open(my $fh, '<', $file);
    while (my $row = $csv->getline( $fh )) {
        $code->($row);
    }
    $csv->eof or $csv->error_diag();
    close($fh);
}

# Output table + row order
my %table;
my @order;

# Table 1
read_file($ARGV[0], sub {
    my($row) = @_;

    #print "ROW 1 @{ $row }\n";
    my($col1, $col2) = @{ $row }[1,2];

    # column_1, column_2 define key
    my $key = "${col1}${col2}";
    #print "KEY 1 ${key}\n";

    # table 1 defines order
    push(@order, $key);
    # ID, column_1, column_2, column_3 from table 1
    $table{$key} = $row;
});

# Table 2
read_file($ARGV[1], sub {
    my($row) = @_;

    #print "ROW 2 @{ $row }\n";
    my($col4, $col5, $col6) = @{ $row };

    # column_4, column_5 define key
    my $key = "${col4}${col5}";
    #print "KEY 2 ${key}\n";

    # column_6 from table 2
    push(@{ $table{$key} }, $col6);
});

# Table 3
read_file($ARGV[2], sub {
    my($row) = @_;

    #print "ROW 3 @{ $row }\n";
    my($col7, $col8, $col9, $col10) = @{ $row };

    # column_7, column_10 define key
    my $key = "${col7}${col10}";
    #print "KEY 3 ${key}\n";

    # column_7, column_8 from table 2
    push(@{ $table{$key} }, $col7, $col8);
});

foreach my $key (@order) {
    $csv->print(\*STDOUT, $table{$key});
}

exit 0;

测试运行:

$ perl dummy.pl dummy1.txt dummy2.txt dummy3.txt 
A       100     100001  X       X       100     120000
B       100     99999   Y       Y       100     66666
C       100     88888   Z       Z       100     77777
D       99      100001  Y       Y       99      100000
E       99      88888   Z       Z       99      44444
© www.soinside.com 2019 - 2024. All rights reserved.