2014-01-24 134 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