遺伝子配列を含むファイルがあります。たとえば、次のようになります。
ATGTGGATGGTGGGTTACAATGAAGGTGGTGAGTTCAACATGGCTGATTATCCATTCAGTGGAAGGAAACTAAGGCCTCTCATTCCAAGACCAGTCCCAGTCCCTACTACTTCTCCTAACAGCACTTCAACTATAACTCCTTCCTTAAACCGCATTCATGGTGGCAATGATTTATTTTCACAATATCATCACAATCTGCAGCAGCAAGCATCAGTAGGAGATCATAGCAAGAGATCAGAGTTGAATAATAATAATAATCCATCTGCAGCAGTTGTGGTGAGTTCAAGATGGAATCCAACACCAGAACAGTTAAGAGCACTGGAAGAATTGTATAGAAGAGGAACAAGAACACCTTCTGCTGAGCAAATCCAACAAATAACTGCCCAGCTTAGAAAATTTGGAAAAATTGAAGGCAAAAATGTTTTCTATTGGTTTCAGAATCACAAAGCCAGAGAAAGGCAAAAACGACGGCGTCAAATGGAATCAGCAGCTGCTGAGTTTGATTCTGCTATTGAAAAGAAAGACTTAGGCGCAAGTAGG
ACAGTGTTTGAAGTTGAACACACTAAAAACTGGCTACCATCTACAAATTCCAGTACCAGTACTCTTCATCTTGCAGAGGAATCTGTTTCAATTCAAAGGTCAGCAGCAGCAAAAGCAGATGGATGGCTCCAATTCGATGAAGCAGAATTACAGCAAAGAAGAAACTTTATGGAAAGGAATGCCACGTGGCATATGATGCAGTTAACTTCTTCTTGTCCTACAGCTAGCATGTCCACCACAACCACAGTAACAACTAGACTTATGGACCCAAAACTCATCAAGACCCATGAACTCAACTTATTCATTTCACCTCACACATACAAAGAAAGAGAAAACGCTTTTATCCACTTAAATACTAGTAGTACTCATCAAAATGAATCTGATCAAACCCTTCAACTTTTCCCAATAAGGAATGGAGATCATGGATGCACTGATCATCATCATCATCATCATAACATTATCAAAGAGACACAGATATCAGCTTCAGCAATCAATGCACCCAACCAGTTTATTGAGTTTCTTCCCTTGAAAAACTGA
上記の文字列で「ATG」部分文字列の発生回数を計算しようとしています(改行なしで1行のみ)。私のファイルには数十のこれらのシーケンスが含まれており、各シーケンスに「ATG」がいくつあるかを計算できるようにしたいです。各シーケンスは空行で他のシーケンスと区別される。
grepを試しましたが、どのオプションを使用するのかわかりません(grepがトリックを実行している場合)、Googleでawkの例を検索しましたが、オプションが見つかりませんでした。
答え1
ATG
各行の発生回数を返します。
awk -F'ATG' 'NF{print NF-1}' testfile
これは、1 つ以上の行を含むファイルに適用されます。
実施例1
次のテストファイルを検討してください。
$ cat testfile
xxATGxxATG
ATGxxxATGxxx
xxATGxxxxATGxxATGxx
このコードは、ATGの発生回数を正しく計算します。
$ awk -F'ATG' 'NF{print NF-1}' testfile
2
2
3
実施例2
現在のバージョンの質問例を使用すると、次のようになります。
$ cat >file1
ATGTGGATGGTGGGTTACAATGAAGGTGGTGAGTTCAACATGGCTGATTATCCATTCAGTGGAAGGAAACTAAGGCCTCTCATTCCAAGACCAGTCCCAGTCCCTACTACTTCTCCTAACAGCACTTCAACTATAACTCCTTCCTTAAACCGCATTCATGGTGGCAATGATTTATTTTCACAATATCATCACAATCTGCAGCAGCAAGCATCAGTAGGAGATCATAGCAAGAGATCAGAGTTGAATAATAATAATAATCCATCTGCAGCAGTTGTGGTGAGTTCAAGATGGAATCCAACACCAGAACAGTTAAGAGCACTGGAAGAATTGTATAGAAGAGGAACAAGAACACCTTCTGCTGAGCAAATCCAACAAATAACTGCCCAGCTTAGAAAATTTGGAAAAATTGAAGGCAAAAATGTTTTCTATTGGTTTCAGAATCACAAAGCCAGAGAAAGGCAAAAACGACGGCGTCAAATGGAATCAGCAGCTGCTGAGTTTGATTCTGCTATTGAAAAGAAAGACTTAGGCGCAAGTAGG
ACAGTGTTTGAAGTTGAACACACTAAAAACTGGCTACCATCTACAAATTCCAGTACCAGTACTCTTCATCTTGCAGAGGAATCTGTTTCAATTCAAAGGTCAGCAGCAGCAAAAGCAGATGGATGGCTCCAATTCGATGAAGCAGAATTACAGCAAAGAAGAAACTTTATGGAAAGGAATGCCACGTGGCATATGATGCAGTTAACTTCTTCTTGTCCTACAGCTAGCATGTCCACCACAACCACAGTAACAACTAGACTTATGGACCCAAAACTCATCAAGACCCATGAACTCAACTTATTCATTTCACCTCACACATACAAAGAAAGAGAAAACGCTTTTATCCACTTAAATACTAGTAGTACTCATCAAAATGAATCTGATCAAACCCTTCAACTTTTCCCAATAAGGAATGGAGATCATGGATGCACTGATCATCATCATCATCATCATAACATTATCAAAGAGACACAGATATCAGCTTCAGCAATCAATGCACCCAACCAGTTTATTGAGTTTCTTCCCTTGAAAAACTGA
その結果は次のとおりです。
$ awk -F'ATG' 'NF{print NF-1}' file1
9
15
どのように動作しますか?
awk はファイルの各行を暗黙的に繰り返します。各行はフィールドで区切られます。
-F'ATG'
これは awk に
ATG
フィールド区切り文字として使用するように指示します。NF{print NF-1}
これは awk に空でない行ごとにフィールド数から 1 を引いた値を出力するように指示します。
(空白行のフィールド数
NF
は0です。したがって、これらの行の条件はNF
falseと評価され、効果的にスキップされます。)
答え2
~からman grep
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.
だから、試してみることができます
$ grep -o 'ATG' file | wc -l
答え3
John1024のテストファイルを使用して、tachomiのgrep -oのアイデアを改善します。これは、数千の行を作成し、後で正確に追跡する必要がある場合に備えて、数を含め、入力ファイルのどの行に対応する数があるかを示す方法です。カウントはから来ました。
最初は、John1024のテストファイルとは少し異なるバージョンのサンプルファイルです。
$ cat testfile2
xxATGxxATG
ATGxxxATGxxx
xxATGxxxxATGxxATG
-n
元の入力に行番号マークを追加すると、次のようになります。
$ grep -no ATG testfile2
1:ATG
1:ATG
3:ATG
3:ATG
5:ATG
5:ATG
5:ATG
最後に、uniq -c
以下を使用して計算します。
$ grep -no ATG testfile2 | uniq -c
2 1:ATG
2 3:ATG
3 5:ATG
これで、数ATG
と数が出た(入力ファイルの)行番号があります。
以下を使用して数だけ表示するように変換することもできますawk
。
$ grep -no ATG testfile2 | uniq -c | awk '{print $1}'
2
2
3
awk は$1
最初のフィールドを表します。
答え4
本当に楽しく楽しみたい場合は、awk
次のようにしてください。
echo -e "test one - test two - test three\ntest four - test five\nnope six\ntest seven"
test one - test two - test three
test four - test five
nope six
test seven
...
echo -e "test one - test two - test three\ntest four - test five\nnope six\ntest seven" | awk -v myVar="test" 'BEGIN{count=0}; {thisLine=gsub(myVar,"&"); count=count+thisLine; print "\"" myVar "\" in line " NR ": " thisLine}; END{print "Total number of \"" myVar "\": " count}'
"test" in line 1: 3
"test" in line 2: 2
"test" in line 3: 0
"test" in line 4: 1
Total number of "test": 6
分解:
echo -e "test one - test two - test three\ntest four - test five\nnope six\ntest seven" |\ ## echo -e tells bash that '\n' is a new line
awk -v myVar="test" ' ## -v set an awk variable
BEGIN{
count=0
}; ## Begins with a 'count' variable set to zero
{ ## Now, for each line...
thisLine=gsub(myVar,"&"); ## Set var for number of myVar in the line, since we're using it twice
count=count+thisLine; ## Add number in line to total count
print "\"" myVar "\" in line " NR ": " thisLine ## print for the line: myVar in quotes, line number, then count in line
};
END{
print "Total number of \"" myVar "\": " count ## End with total count
}
'