基于第一列合并两个文件,并为每个键返回多个值

时间:2012-09-11 21:04:10

标签: perl

我是Perl的新手,所以希望这有一个快速的解决方案。

我一直在尝试根据密钥合并两个文件。问题是有多个值而不是它返回的值。有没有办法循环哈希以获得它可能获得的1-10个更多值?

示例:

文件输入1:

12345|AA|BB|CC
23456|DD|EE|FF

文件输入2:

12345|A|B|C
12345|D|E|F
12345|G|H|I
23456|J|K|L
23456|M|N|O
32342|P|Q|R

我放入最后一个的原因是因为第二个文件有很多我不想要的值,但文件1我想要所有的值。我想要的结果是这样的:

通缉输出:

12345|AA|BB|CC|A|B|C
12345|AA|BB|CC|D|E|F
12345|AA|BB|CC|G|H|I
23456|DD|EE|FF|J|K|L
23456|DD|EE|FF|M|N|O

附件是我目前使用的代码。它给出了如下输出:

输出我的消息:

12345|AA|BB|CC|A|B|C
23456|DD|EE|FF|J|K|L

到目前为止我的代码:

#use strict; 
#use warnings; 

open file1, "<FILE1.txt"; 
open file2, "<FILE2.txt"; 

while(<file2>){

    my($line) = $_; 
    chomp $line; 
    my($key, $value1, $value2, $value3) = $line =~ /(.+)\|(.+)\|(.+)\|(.+)/; 
    $value4 = "$value1|$value2|$value3"; 
    $file2Hash{$key} = $value4; 
} 

while(<file1>){ 

    my ($line) = $_; 
    chomp $line; 
    my($key, $value1, $value2, $value3) = $line =~/(.+)\|(.+)\|(.+)\|(.+)/; 

    if (exists $file2Hash{$key}) {

        print $line."|".$file2Hash{$key}."\n";
    } 
    else {
        print $line."\n";
    } 
} 

感谢您提供的任何帮助,

3 个答案:

答案 0 :(得分:2)

你的整体想法是合理的。但是在file2中,如果遇到已定义的键,则用新值覆盖它。为了解决这个问题,我们在哈希中存储了一个数组(-ref)。

所以在你的第一个循环中,我们这样做:

push @{$file2Hash{$key}}, $value4; 

@{...}只是数组解除引用语法。

在你的第二个循环中,我们这样做:

if (exists $file2Hash{$key}){
  foreach my $second_value (@{$file2Hash{$key}}) {
    print "$line|$second_value\n";
  }
} else {
  print $line."\n";
}

除此之外,您可能希望使用%file2Hash声明my,以便重新启用strict

答案 1 :(得分:1)

哈希中的键必须是唯一的。如果file1中的键是唯一的,请使用file1创建哈希。如果密钥在任一文件中都不是唯一的,则必须使用更复杂的数据结构:数组的散列,即在每个唯一密钥上存储多个值。

答案 2 :(得分:-1)

我假设FILE1.txt中的每个键都是唯一的,并且每个唯一键在FILE2.txt中至少有一个对应的行。

您的方法非常接近您的需求,您应该使用FILE1.txt来创建哈希(如前所述here)。

以下内容应该有效:

#!/usr/bin/perl

use strict;
use warnings;

my %file1hash;

open file1, "<", "FILE1.txt" or die "$!\n";
while (<file1>) {
    my ($key, $rest) = split /\|/, $_, 2;
    chomp $rest;
    $file1hash{$key} = $rest;
}
close file1;

open file2, "<", "FILE2.txt" or die "$!\n";
while (<file2>) {
    my ($key, $rest) = split /\|/, $_, 2;
    if (exists $file1hash{$key}) {
        chomp $rest;
        printf "%s|%s|%s\n", $key, $file1hash{$key}, $rest;
    }
}
close file2;

exit 0;