2014-01-24 181 views
2

我正在使用一個文件中的列查找另一個文件中的值。第二個文件非常大,我想用awk在單個傳遞中查找所有值。我曾嘗試用關聯數組來做這件事,但是我很難理解如何讓出我想要的東西。我想要F1,使用$ 2在F2中查找值,並獲得我在下面顯示的輸出,即從F1開始的$ 0作爲標題,然後從F2中排序$ 10併爲每個唯一字符串計數(即通過排序| uniq -c)。循環AWK關聯數組

F1 

+ID=dnaK.p01 12121 TTGGGCAGTTGAAACCAGACGTTTCGCCCCTATTACAGAC[T]CACAACCACATGATGACCG 

F2 

solid309_20110930_FRAG_BC_bcSample12273_1541_657_F3  0  NC_012759  12121 42  35M  *  0  0  ACACAACCACATGATGACCGAATATATAGTGGCTC  [email protected]@[email protected]<[email protected]:>>&B7 
solid309_20110930_FRAG_BC_bcSample12295_323_1714_F3  0  NC_012759  12121 42  35M  *  0  0  ACACAACCACATGATGACCGAATATATAGTGGAGA  [email protected]@[email protected]@[email protected]@@[email protected]<[email protected]@=><6*7=?9993>4&7, 
solid309_20110930_FRAG_BC_bcSample12325_1148_609_F3  0  NC_012759  12121 42  35M  *  0  0  ACACAACCACATGATGACCGAATATATAGTGGAGA  [email protected]@[email protected]@@[email protected][email protected]<.<==:6:1>9(<- 
solid309_20110930_FRAG_BC_bcSample11796_1531_1170_F3 0  NC_012759  12122 42  35M  *  0  0  CACAACCACATGATGACCGAATATATAGTGGAGCA  '&&+&&)&')&0(.,',(.3+&&&+,&&&&&&&&& 
solid309_20110930_FRAG_BC_bcSample12110_1166_1149_F3 0  NC_012759  12122 42  35M  *  0  0  CACAACCACATGATGACCGAATATATAGTGGAGAC  -(:18)538;,9277*'8:<)&,0-+)//3&'1+' 
solid309_20110930_FRAG_BC_bcSample183_686_962_F3  0  NC_012759  12123 42  35M  *  0  0  ACAACCACATGATGACCGAATATATAGTGGAGTGC  BB?BBBB;[email protected];@[email protected]@[email protected]*>[email protected] 

我用下面的腳本

for line in `awk '{if ($1~"-") print ($2-34);else print $2}' $1` 
do 
awk -v l=$line '{if ($1~"-") l=l+34;if ($2==l) print }' $1 >> f2 
awk -v l=$line '{if ($4==l) print $10}' URA2.sam | sort | uniq -c |awk '{if ($1>15) print}'>> f2 
done 

這需要多道使用awk每行的事情了。我想我可以使用來自F1做一個關聯數組與一個做到這一點通過。 F2按$ 4排序。我使用以下腳本來嘗試獲取我想要的輸出。

awk 'FNR==NR{a[$2]=$0;next}$4 in a{print $10}' f1 f2 | sort | uniq -c 
+0

考慮編輯您的問題,以顯示當前輸出與'awk' 1襯什麼,如果你刪除次e排序| uniq -c。這似乎非常接近應該工作的東西,因爲您的描述「使用一個文件中的列查找另一個文件中的值」。但是你的示例輸出結果並不符合你所要求的要求',然後按F2排序$ 10,併爲每個唯一字符串計數。祝你好運。 – shellter

+0

輸出的每個頭文件是否真的需要排序,還是足以讓它與計數一起唯一? –

+0

@EdMorton下面的值需要針對uniq程序進行排序,因爲它僅在確定字符串是否爲uniq時考慮下一行。 – jeffpkamp

回答

4

這裏的使用GNU AWK輸出asorti()delete array

$ cat tst.awk 
function prtCounts( val,sorted,idx) { 
    if (prev in f1) { 
     print f1[prev] 
     asorti(count,sorted) 
     for (idx=1; idx in sorted; idx++) { 
      val = sorted[idx] 
      print count[val], val 
     } 
    } 
    delete count 
} 

NR==FNR { f1[$2] = $0; next } 

{ 
    if ((FNR>1) && ($4!=prev)) 
     prtCounts() 
    count[$10]++ 
    prev = $4 
} 

END { prtCounts() } 

$ gawk -f tst.awk file1 file2 
a 1 b c d 
1 BALH 
2 BLAH 
b 2 b c d 
1 HAHA 
2 ZAHA 
+0

這對測試很好,但我遇到了真正的數據集問題。在真實數據集中,它給了我每個獨特$ 4的獨特字符串的總和,而不僅僅是F1文件中指定的字符串。 – jeffpkamp

+0

@jeffpkamp - 實際上,我想我理解你描述的情況,所以我用解決方案更新了我的答案。我剛剛發佈帶有排序輸出的gawk版本,保持簡短... –

+0

現在我沒有得到任何輸出。有沒有一個地方可以發佈兩個小文件來測試?價值256K的數據在帖子上看起來很難看:/。 – jeffpkamp

1

我將處理F1第一和使用的副陣列到第二個字段保存,作爲密鑰和整個線路作爲值。然後你纔會有處理F2一次,每一次,第四場的變化,打印重複值的數量在第十場,如:

awk ' 
    ## Process F1. 
    FNR == NR { 
     f1[$2] = $0 
     next 
    } 

    ## Process F2. 
    { 
     if (FNR == 1 || prev_key == $4) { 
      f2[$10]++ 
     } 
     else { 
      printf "%s\n", f1[prev_key] 
      for (key in f2) { 
       printf "%d %s\n", f2[key], key 
      } 
      delete f2 
      f2[$10]++ 
     } 
     prev_key = $4 
    } 

    END { 
     printf "%s\n", f1[prev_key] 
     for (key in f2) { 
      printf "%d %s\n", f2[key], key 
     } 
    } 
' F1 F2 

它產生:

a 1 b c d 
1 BALH 
2 BLAH 
b 2 b c d 
2 ZAHA 
1 HAHA