2016-08-12 3 views
0

Я сделал эту команду awk в сценарии оболочки, чтобы подсчитать общее количество событий в $ 4 и $ 5.awk Количество вхождений

awk -F" " '{if($4=="A" && $5=="G") {print NR"\t"$0}}' file.txt > ag.txt && cat ag.txt | wc -l 
awk -F" " '{if($4=="C" && $5=="T") {print NR"\t"$0}}' file.txt > ct.txt && cat ct.txt | wc -l 

awk -F" " '{if($4=="T" && $5=="C") {print NR"\t"$0}}' file.txt > tc.txt && cat ta.txt | wc -l 
awk -F" " '{if($4=="T" && $5=="A") {print NR"\t"$0}}' file.txt > ta.txt && cat ta.txt | wc -l 

Выходной сигнал: #### (номер) в оболочке. Но я хочу избавиться от > ag.txt && cat ag.txt | wc -l и вместо этого получить выход в оболочке, такой как AG = ####.

Это входной формат:

>seq1 284 284 A G 27 100 16 11 16 11 
>seq1 266 266 C T 27 100 16 11 16 11 
>seq1 185 185 T - 24 100 10 14 10 14 
>seq1 194 194 T C 24 100 12 12 12 12 
>seq1 185 185 T AAA 24 100 10 14 10 14 
>seq1 194 194 A G 24 100 12 12 12 12 
>seq1 185 185 T A 24 100 10 14 10 14 

Я хочу, чтобы результат, как это в оболочке или в файле для одного вхождений не другие узоры.

AG 2 
CT 1 
TC 1 
TA 1 
+1

Можете ли вы показать нам форматированный вывод вы прицеливания для, и, возможно, включают в себя некоторые образец ввода для тестирования с? – ghoti

+0

Добавленный вами результат не соответствует сценарию образца, который вы написали. Вы действительно хотите что-то, что будет считать пары, или просто считать «A» и «G»? – ghoti

+0

Я делаю это один за другим. Таким образом, в основном я использую команду awk в сценарии оболочки. – Ramon

ответ

4

Да, все, что вы пытаетесь сделать, может быть сделано в сценарии awk. Вот как бы я рассчитывать строки, основываясь на состоянии:

awk -F" " '$4=="A" && $5=="G" {n++} END {printf("AG = %d\n", n)}' file.txt 
  • Awk сценарии состоят из condition { statement } пар, так что вы можете сделать прочь с if целиком - это неявный.
  • n++ увеличивает счетчик при выполнении условия.
  • Магическое условие END истинно после обработки последней строки ввода.

Это ты, что ты? Почему вы добавили NR к вашему выходу, если все, что вам нужно, это счет линии?

О, и вы можете подтвердить, действительно ли вам нужно -F" ". По умолчанию awk разбивается на пробелы. Я думаю, этот вариант будет необходим только в том случае, если ваши поля содержат встроенные вкладки.


UPDATE # 1 на основе отредактированной вопрос ...

Если то, что вы на самом деле после того, как счетчик пара, AWK массив может быть путь. Что-то вроде этого:

awk '{a[$4 $5]++} END {for (pair in a) printf("%s %d\n", pair, a[pair])}' file.txt 

Прорыв.

  • Первый оператор работает на каждой строке, и увеличивает счетчик, который является индекс массива (a[]), ключ строится из $4 и $5.
  • В блоке END мы проходим через массив в цикле for и для каждого индекса печатаем имя индекса и его значение.

Выход не будет в каком-либо конкретном порядке, так как awk не гарантирует порядок массива. Если с тобой все в порядке, тогда этого должно быть достаточно. Он также должен быть довольно эффективным, поскольку его максимальное использование памяти основано на общем количестве доступных комбинаций, которое является ограниченным набором.

Пример:

$ cat file 
>seq1 284 284 A G 27 100 16 11 16 11 
>seq1 266 266 C T 27 100 16 11 16 11 
>seq1 227 227 T C 25 100 13 12 13 12 
>seq1 194 194 A G 24 100 12 12 12 12 
>seq1 185 185 T A 24 100 10 14 10 14 
$ awk '/^>seq/ {a[$4 $5]++} END {for (p in a) printf("%s %d\n", p, a[p])}' file 
CT 1 
TA 1 
TC 1 
AG 2 

ОБНОВЛЕНИЕ # 2 на основе пересмотренных входных данных и документированных ранее требований.

С дополнительными данными вы все равно можете сделать это с помощью одного прогона awk, но, конечно, скрипт awk становится все более сложным с каждым новым требованием. Давайте попробуем это как более однострочник:

$ awk 'BEGIN{v["G"]; v["A"]; v["C"]; v["T"]} $4 in v && $5 in v {a[$4 $5]++} END {for (p in a) printf("%s %d\n", p, a[p])}' i 
CT 1 
TA 1 
TC 1 
AG 2 

Это работает первым (в магическом BEGIN блока) определение массива, v[], записывать «действительную» запись. Условие на счетчике просто проверяет, что и $4, и $5 содержат элементы массива. Все остальное работает одинаково.

На данный момент, когда скрипт работает на нескольких строках, я бы, вероятно, разделил его на небольшой файл. Это может быть даже отдельный сценарий.

#!/usr/bin/awk -f 

BEGIN { 
    v["G"]; v["A"]; v["C"]; v["T"] 
} 

$4 in v && $5 in v { 
    a[$4 $5]++ 
} 

END { 
    for (p in a) 
    printf("%s %d\n", p, a[p]) 
} 

Гораздо легче читать таким образом.

И если ваша цель состоит в том, чтобы засчитывать ТОЛЬКО комбинации, упомянутые в вашем вопросе, вы можете обрабатывать массив несколько иначе.

#!/usr/bin/awk -f 

BEGIN { 
    a["AG"]; a["TA"]; a["CT"]; a["TC"] 
} 

($4 $5) in a { 
    a[$4 $5]++ 
} 

END { 
    for (p in a) 
    printf("%s %d\n", p, a[p]) 
} 

Это подтверждает только то, что уже есть индексы массива, которые NULL в BEGIN.

Скобки в условии приращения не требуются и включены только для ясности.

+0

Спасибо. Я добавил свой файл ввода. Можете ли вы улучшить код для всех шаблонов? – Ramon

+0

Ваш первый код работает отлично. Как сделать для разных случаев сразу? – Ramon

+0

Ваш обновленный код печатает другие исправления, которые я не хочу. – Ramon

0

Просто сосчитать все распечатайте те, что вы заботитесь о:

$ awk '{cnt[$4$5]++} END{split("AG CT TC TA",t); for (i=1;i in t;i++) print t[i], cnt[t[i]]+0}' file 
AG 2 
CT 1 
TC 1 
TA 1 

Обратите внимание, что это будет производить отсчет нуля для любого из ваших целевых пар, которые не появляются в вашем входе, например, если вы хотите, подсчет «XY» слишком:

$ awk '{cnt[$4$5]++} END{split("AG CT TC TA XY",t); for (i=1;i in t;i++) print t[i], cnt[t[i]]+0}' file 
AG 2 
CT 1 
TC 1 
TA 1 
XY 0 

Если это желательно, проверить, если другие решения делают то же самое.

На самом деле, это может быть то, что вы действительно хотите, чтобы убедиться $ 4 и $ 5 одиночные прописные буквы:

$ awk '$4$5 ~ /^[[:upper:]]{2}$/{cnt[$4$5]++} END{for (i in cnt) print i, cnt[i]}' file 
TA 1 
AG 2 
TC 1 
CT 1 
Смежные вопросы