[英]awk Count number of occurrences
我在shell腳本中執行了這個awk命令,以計算$ 4和$ 5的總出現次數。
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
在shell中,輸出為####(數字)。 但是我想擺脫> ag.txt && cat ag.txt | wc -l
> ag.txt && cat ag.txt | wc -l
,而是在shell中獲取輸出,例如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
是的,您嘗試執行的所有操作都可以在awk腳本中完成。 這是我根據條件計算行數的方法:
awk -F" " '$4=="A" && $5=="G" {n++} END {printf("AG = %d\n", n)}' file.txt
condition { statement }
對組成,因此您可以完全消除– if
是隱式的。 n++
都會增加一個計數器。 END
最后一行輸入后,魔術條件END
為true。 這是你所追求的嗎? 如果只需要行數,為什么還要在輸出中添加NR
?
哦,您可能需要確認是否確實需要-F" "
。 默認情況下,awk在空白處分割。 我認為,僅當您的字段包含嵌入式選項卡時才需要此選項。
根據已編輯的問題更新#1 ...
如果您真正想要的是配對計數器,則可以使用awk 數組 。 像這樣:
awk '{a[$4 $5]++} END {for (pair in a) printf("%s %d\n", pair, a[pair])}' file.txt
這是細分。
$4
和$5
的數組( a[]
)上的索引。 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])
}
這只會驗證已經具有數組索引的東西,每個BEGIN
為NULL。
增量條件中的括號不是必需的,僅為了清楚起見,將其包括在內。
只計算它們,然后打印您關心的那些:
$ 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.