2012-11-06 23 views
6

Tôi có hai tập tin như hình dưới đây là tab-delimited:Tham gia hai tập tin sử dụng awk

tập tin Một

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

tập tin B

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

Tôi muốn tham gia hai tập tin dựa trên 3 cột có "chr1", "123" và "aa" và thêm hai cột đầu tiên từ tệp B vào tệp A, sao cho kết quả đầu ra đó như sau: đầu ra:

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 

Ai đó có thể giúp bạn thực hiện việc này khi đang bận. Nếu có thể bằng cách sử dụng awk oneliners?

+5

[Bạn đã làm gì cố gắng cho đến nay] (http://whathaveyoutried.com/)? – doublesharp

Trả lời

11

Dưới đây là một cách tiếp cận sử dụng 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 

Giải thích:

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 

Edit:

Đối với vấn đề 3 lĩnh vực bạn đơn giản thêm trường bổ sung:

$ 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

tôi đã sửa đổi vấn đề ban đầu. Coudl bạn cung cấp giải pháp cho điều đó. – chas

+0

Bạn chỉ cần thêm trường bổ sung vào, xem chỉnh sửa. –

+0

Cảm ơn. Tôi đã thêm trường bổ sung theo cách sau đã xảy ra: awk 'NR == FNR {a [$ 3, $ 4, $ 5] = $ 1OFS $ 2OFS $ 3; next} {$ 6 = a [$ 1, $ 2]; print} 'OFS =' \ t 'fileb filea. – chas

2

Bạn có thể sử dụng join, nhưng đường dẫn trở nên phức tạp đến mức có thể dễ dàng chuyển sang ngôn ngữ mạnh hơn như 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/:/ /' 

giải pháp Perl, sử dụng một băm để nhớ tất cả các thông tin:

#!/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: Giải pháp Perl được thêm vào. – choroba

Các vấn đề liên quan