2016-09-27 24 views
1

我有一個輸入的數據,如:檢查和計數複製行

chr17 41243232 41243373 BRCA1_ex11 
chr17 41243232 41243373 BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
chr17 41243639 41243811 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23 
chr13 32954112 32954208 BRCA2_ex24 

,我需要檢查重複行$2$3行,如果是重複的,我需要合併成一個線和$4列打印用逗號分隔。

輸出:

chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
chr17 41243639 41243811 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24 

是否有任何AWK解決簡單的過程,這樣的數據?我將不勝感激解釋。輸入和輸出是製表符分隔的格式。注意:第一,第二和第三個字段是相等的。

我的嘗試是:

awk -v OFS="\t" '{i=$2 FS $1 FS $3 FS $4} {a[i]=!a[i]?$4:a[i] "," $4} END {for (l in a) {print l,a[l]}}' infile 

謝謝你的任何想法。

+2

如果第一個字段不同而第二個和第三個字段相同會怎麼樣?你有沒有嘗試過任何一個機會? –

+0

@JamesBrown謝謝你的好問題。第一場與第二場和第三場相同。是的,我試圖在awk中進行數組 - 但仍然是自學。我將編輯我的帖子.. – Paul

回答

2
$ cat script.awk 
{ 
    a[$2 OFS $3] = $1     # store $1, last instance 
    b[$2 OFS $3] = b[$2 FS $3] $4 "," # append the $4s 
} 
END { 
    for (i in a) {      # order is awk default 
     sub(/,$/, "", b[i])   # remove trailing "," 
     print a[i], i, b[i]   # print 
    } 
} 

運行:

$ awk -f script.awk infile 
chr17 41243471 41243644 BRCA1_ex11 
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12 
chr17 41243639 41243811 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24 
+0

看起來這是偉大的工作。你們有解決方案詹姆斯,謝謝。 – Paul

1

只是

i=$1 FS $2 FS $3 

,並可能取代第一任務通過sed過濾輸出用標籤來代替空格:

... | sed 's// /g' 

     space---^ ^--- TAB 

輸出:

chr13 32954112  32954208  BRCA2_ex23,BRCA2_ex24 
chr17 41243639  41243811  BRCA1_ex11 
chr17 41243232  41243373  BRCA1_ex11,BRCA1_ex12 
chr17 41243471  41243644  BRCA1_ex11 
1

如果perl是好的:上空間

$ cat ip.txt 
chr17 41243232 41243373 BRCA1_ex11 
chr17 41243232 41243373 BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
chr17 41243639 41243811 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23 
chr13 32954112 32954208 BRCA2_ex24 

$ perl -ale '$k = join "\t",@F[0..2]; $h{$k} .= $h{$k} ? ",$F[3]" : $F[3]; END{ print "$_\t$h{$_}" foreach (keys %h) }' ip.txt 
chr17 41243639 41243811 BRCA1_ex11 
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24 
  • -ale分割輸入線和保存到@F陣列,條帶換行從輸入線和用於打印語句
  • $k = join "\t",@F[0..2]鍵添加新行使用 - 前3個元素加入tab
  • $h{$k} .= $h{$k} ? ",$F[3]" : $F[3]將值附加到散列變量ble,加,取決於現有值是否爲空
  • END{ print "$_\t$h{$_}" foreach (keys %h) }所有行處理後,打印鍵和值之間用tab分隔。鍵的順序是隨機的,通過提取關鍵,使用正則表達式值

備用方式:

$ perl -nle '($k,$v)=/^(.*?)\s+(\S+)$/; $h{$k} .= $h{$k} ? ",$v" : $v; END{print "$_\t$h{$_}" foreach (keys %h) }' ip.txt 
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24 
chr17 41243639 41243811 BRCA1_ex11 
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
1
$ cat tst.awk 
{ 
    curr = $2 FS $3 

    if (curr == prev) { 
     buf = buf "," $NF 
    } 
    else { 
     if (NR>1) { 
      print buf 
     } 
     buf = $0 
    } 

    prev = curr 
} 
END { print buf } 

$ awk -f tst.awk file 
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12 
chr17 41243471 41243644 BRCA1_ex11 
chr17 41243639 41243811 BRCA1_ex11 
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24 

這個和@JamesBrown's solution之間的差異是:

  1. 這僅存儲1個輸出詹姆斯'存儲整個文件的時間在內存中。
  2. 這將按照它們在輸入中出現的順序打印行,而James將以「隨機」(散列)順序打印它們。
  3. 這取決於您輸入的密鑰($ 2 & $ 3)值是否與樣本中顯示的值相同,而詹姆斯將以任何順序輸入。