2012-11-06 4 views
6

を使用して2つのファイルを結合:私は2つのファイルを結合したい私はそれ以下に示すような2つのファイルがタブで区切られているのawk

chr1 123 aa b c d 
chr1 234 a b c d 
chr1 345 aa b c d 
chr1 456 a b c d 
.... 

ファイルB

xxxx abcd chr1 123 aa c d e 
yyyy defg chr1 345 aa e f g 
... 

ファイル"chr1"、 "123"、 "aa"の3つの列に基づいて、ファイルBからファイルAに最初の2つの列を追加すると、出力は次のようになります。 出力:

chr1 123 aa b c d xxxx abcd 
chr1 234 a  b c d 
chr1 345 aa b c d yyyy defg 
chr1 456 a b c d 

誰でもawkでこれを行うのに役立つでしょうか。可能であれば、awk onelinerを使用しますか?

+5

[あなたがこれまでに試してみました何](http://whathaveyoutried.com/)? – doublesharp

答えて

11

awkを使用して一つのアプローチです:

$ awk 'NR==FNR{a[$3,$4]=$1OFS$2;next}{$6=a[$1,$2];print}' OFS='\t' fileb filea 
chr1 123  a b c  xxxx abcd 
chr1 234  a b c 
chr1 345  a b c  yyyy defg 
chr1 456  a b c 

は説明:

NR==FNR    # current recond num match the file record num i.e in filea 
a[$3,$4]=$1OFS$2 # Create entry in array with fields 3 and 4 as the key 
next    # Grab the next line (don't process the next block) 
$6=a[$1,$2]   # Assign the looked up value to field 6 (+rebuild records) 
print    # Print the current line & the matching entry from fileb ($6) 

OFS='\t'   # Seperate each field with a single TAB on output 

編集:あなたは、単純な余分なフィールドを追加3分野の問題については

$ awk 'NR==FNR{a[$3,$4,$5]=$1OFS$2;next}{$6=a[$1,$2,$3];print}' OFS='\t' fileb filea 
chr1 123 aa  b  c  xxxx  abcd 
chr1 234 a  b  c 
chr1 345 aa  b  c  yyyy  defg 
chr1 456 a  b  c 
+0

私は元の問題を修正しました。あなたはそれを解決するためにCoudlを提供します。 – chas

+0

追加のフィールドを追加するだけです。編集を参照してください。 –

+0

ありがとうございます。 awkのNR == FNR {a [$ 3、$ 4、$ 5] = $ 1OFS $ 2OFS $ 3;次の} {$ 6 = a [$ 1、$ 2]; print} 'OFS =' \ t 'fileb filea。 – chas

2

joinを使用することもできますが、パイプラインが複雑になり、Perlのようなより強力な言語に切り替えるのが簡単になる可能性があります。

すべての情報を覚えておくことは、ハッシュを使用して
join -11 -21 -o1.1,1.2,1.3,1.4,1.5,2.4,2.5 \ 
    <(sed 's/ \+/:/' fileA | sort) \ 
    <(sed 's/ \+/:/' fileB | sort) \ 
| join -11 -22 -a1 -o1.1,1.2,1.3,1.4,1.5,1.6,1.7,2.5,2.6 \ 
    - <(sed 's/ \+\([^ ]\+\) \+\([^ ]\+\)/ \1:\2/' fileC | sort -k2) \ 
| sed 's/:/ /' 

Perlのソリューション、:ここで

#!/usr/bin/perl 
use warnings; 
use strict; 

#    key_start key_end keep_from output 
my %files = (A => [0,  1,  2,  [0 .. 3]], 
      B => [0,  1,  2,  [-2, -1]], 
      C => [1,  2,  3,  [-2, -1]], 
      ); 

my %hash; 

for my $file (keys %files) { 
    open my $FH, '<', "file$file" or die "file$file: $!"; 
    while (<$FH>) { 
     my @fields = split; 
     $hash{"@fields[$files{$file}[0], $files{$file}[1]]"}{$file} 
      = [ @fields[$files{$file}[2] .. $#fields] ]; 
    } 
} 

for my $key (sort keys %hash) { 
    print $key, join(' ', q(), 
        grep defined, map { 
         @{ $hash{$key}{$_} }[@{ $files{$_}[-1] }] 
        } sort keys %files), "\n"; 
} 
+0

@ user1779730:Perlソリューションが追加されました。 – choroba

関連する問題