参考第一列将多列转换为行?

时间:2014-06-07 09:38:48

标签: perl bash shell awk grep

这是我的档案A

NoARTInfo_6 hm_database_atg_all bil|qw_N_g8589t1
NoARTInfo_6 alia_query_atg_all  alia|FBgn0028542
NoARTInfo_7 hm_database_atg_all bil|qw_N_g7396t1
NoARTInfo_7 alia_query_atg_all  alia|rmt0034647
WTCArcNu8_1 req_query_atg_all req|nbrL2EG020589
WTCArcNu21_1  hm_database_atg_all bil|qw_N_g5599t1
WTCArcNu21_1  req_query_atg_all req|nbrL2EG004245

我想将文件转换为文件B,看起来像

NoARTInfo_6 hm_database_atg_all bil|qw_N_g8589t1 alia_query_atg_all alia|FBgn0028542
NoARTInfo_7 hm_database_atg_all bil|qw_N_g7396t1  alia_query_atg_all  alia|rmt0034647
WTCArcNu8_1 req_query_atg_all req|nbrL2EG020589
WTCArcNu21_1  hm_database_atg_all bil|qw_N_g5599t1 req_query_atg_all  req|nbrL2EG004245

第一列包含一些重复的标识符(此处为NoARTInfo_6NoARTInfo_7NoARTInfo_6)和一些唯一标识符(此处为NoARTInfo_6)。

第二列和第三列有它们的值。

如果重复第一列id,那么它们应该只在文件B中有一次具有所有值。

3 个答案:

答案 0 :(得分:2)

这个awk应该可以工作:

awk '!a[$1]{b[++n]=$1; a[$1]=$0; next} {k=$1; $1=""; a[k] = a[k] $0}
     END{for (i=1; i<=n; i++) print a[b[i]]}' file
NoARTInfo_6 hm_database_atg_all bil|qw_N_g8589t1 alia_query_atg_all alia|FBgn0028542
NoARTInfo_7 hm_database_atg_all bil|qw_N_g7396t1 alia_query_atg_all alia|rmt0034647
WTCArcNu8_1 req_query_atg_all req|nbrL2EG020589
WTCArcNu21_1  hm_database_atg_all bil|qw_N_g5599t1 req_query_atg_all req|nbrL2EG004245

答案 1 :(得分:1)

#!/usr/bin/perl
use strict;
use warnings;
my %hash;
open (my $fh, "<", "fileA") or die $!;  #Open fileA in read mode
open (my $fh2, ">", "fileB") or die $!; #Open fileB in write mode
while(chomp(my $line=<$fh>)){
    my ($key, @values) = split / /, $line;
    if(exists $hash{$key}){
       my $ref_value = $hash{"$key"};
       push @values, @$ref_value;
       $hash{"$key"} = [@values];   
    }
     else{
       $hash{"$key"} = [@values];
    }
}
foreach(keys %hash){
    print $fh2 "$_ @{$hash{$_}}\n"; #Write to fileB
}
close($fh);
close($fh2);

更短的:

#!/usr/bin/perl
# your code goes here
use strict;
use warnings;
my %hash;
open (my $fh, "<", "fileA") or die $!;  #Open fileA in read mode
open (my $fh2, ">", "fileB") or die $!; #Open fileB in write mode
while(chomp(my $line = <$fh>)){
    my ($k, @vals) = split / /, $line;
    push @{ $hash{$k} }, @vals;
}
foreach(keys %hash){
    print $fh2 "$_ @{$hash{$_}}\n"; #Write to fileB
}

答案 2 :(得分:1)

#!/usr/bin/perl

while (<>) {
  my ($key, @list) = split;
  push(@keys, $key) if !defined $hash{$key};
  push(@{$hash{$key}}, @list);
}
foreach (@keys) {
  print join(' ', ($_, @{$hash{$_}})), "\n";
}

输出

./script.pl data
NoARTInfo_6 hm_database_atg_all bil|qw_N_g8589t1 alia_query_atg_all alia|FBgn0028542
NoARTInfo_7 hm_database_atg_all bil|qw_N_g7396t1 alia_query_atg_all alia|rmt0034647
WTCArcNu8_1 req_query_atg_all req|nbrL2EG020589
WTCArcNu21_1 hm_database_atg_all bil|qw_N_g5599t1 req_query_atg_all req|nbrL2EG004245

我不确定线条的顺序是否重要,但无论如何我保留了它。