2016-08-12 28 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スクリプト内で行うことができます。ここで私は条件に基づいて行をカウントしたい方法は次のとおりです。あなたが離れて完全にifで行うことができますので

awk -F" " '$4=="A" && $5=="G" {n++} END {printf("AG = %d\n", n)}' file.txt 
  • awkのスクリプトは、condition { statement }ペアで構成さ - それは暗黙のです。
  • 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 

ここは故障です。

  • 最初の文は、すべての行で実行され、キー$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の1回の実行でこれを行うことはできますが、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 

これが「有効」レコードを記録する配列、v[]を定義する(魔法BEGINブロックで)最初で動作します。カウンターの条件は、$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いる配列のインデックスを、持っているものを検証します。

増分条件のカッコは必須ではなく、わかりやすくするために記載しています。

+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 

注意を

$ 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 
関連する問題