2014-01-24 3 views
2

Я использую столбец в одном файле для поиска значений в другом файле. Второй файл очень большой, и я хотел бы найти все значения за один проход с awk. Я пробовал делать это с помощью ассоциативного массива, но я был в тупике, как получить доступ, который я хочу. Я хочу взять F1, использовать $ 2 для поиска значений в F2 и получить результат, который я покажу ниже, который равен $ 0 из F1 в качестве заголовка, за которым следуют $ 10 из F2, отсортированные и подсчитанные для каждой уникальной строки (т.е. uniq -c).Looping 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. Это кажется очень близким к чему-то, что должно работать, учитывая ваше описание «использование столбца в одном файле для поиска значений в другом файле». НО ваш пример вывода, похоже, не соответствует вашему заявленному требованию ', за которым следуют $ 10 из F2, отсортированные и подсчитанные для каждой уникальной строки'. Удачи. – 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

Это работает на тест отлично, но у меня возникают проблемы с истинным набором данных. В реальном наборе данных он дает мне сумму строк unqiue для каждого уникального $ 4, а не только тех, которые указаны в файле F1. – jeffpkamp

+0

@jeffpkamp - на самом деле, я ДУМАЮ, Я понимаю ситуацию, которую вы описываете, поэтому я обновил свой ответ с помощью решения. Я только что опубликовал версию gawk с отсортированным результатом, сохраняя ее кратким ... –

+0

теперь я не получаю никакого вывода. Есть ли место, где я могу отправить два небольших файла для тестирования? Данные на 256 Кбайт выглядят уродливо на почте: /. – 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 
Смежные вопросы