awk

2012-11-06 14 views
6

का उपयोग कर दो फ़ाइलों में शामिल होने से पता चला की तरह नीचे जो टैब-सीमांकित हैं मैं दो फ़ाइलें: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 
.... 

फ़ाइल बी

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

मैं दो फ़ाइलों में शामिल करना चाहते "chr1", "123" और "आ" और फ़ाइल बी से पहले दो स्तंभ जोड़ने के ए, ऐसी है कि उत्पादन लग रहा है दायर करने के लिए के साथ 3 कॉलम के आधार पर के रूप में नीचे दिखाया गया है: उत्पादन:

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 में यह करने के लिए किया जा सका। अगर अजीब oneliners का उपयोग कर संभव हो?

+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

धन्यवाद। मैं निम्नलिखित तरीके से अतिरिक्त फ़ील्ड जोड़ रहा था जो गलत हो गया: अजीब 'एनआर == एफएनआर {एक [$ 3, $ 4, $ 5] = $ 1OFS $ 2OFS $ 3; अगला} {$ 6 = एक [$ 1, $ 2]; प्रिंट} 'OFS =' \ t 'fileb filea। – chas

2

आप join उपयोग कर सकते हैं, लेकिन पाइप लाइन पर्ल की तरह एक अधिक शक्तिशाली भाषा को इतना जटिल है कि यह स्विच करने के लिए आसान हो सकता है हो जाता है।

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/:/ /' 

पर्ल समाधान, सभी जानकारी याद करने के लिए एक हैश का उपयोग कर:

#!/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: पर्ल समाधान जोड़ा गया। – choroba

संबंधित मुद्दे