Да, все, что вы пытаетесь сделать, может быть сделано в сценарии 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
.
Скобки в условии приращения не требуются и включены только для ясности.
Можете ли вы показать нам форматированный вывод вы прицеливания для, и, возможно, включают в себя некоторые образец ввода для тестирования с? – ghoti
Добавленный вами результат не соответствует сценарию образца, который вы написали. Вы действительно хотите что-то, что будет считать пары, или просто считать «A» и «G»? – ghoti
Я делаю это один за другим. Таким образом, в основном я использую команду awk в сценарии оболочки. – Ramon