文字列内の部分文字列が繰り返される回数を計算します。

文字列内の部分文字列が繰り返される回数を計算します。

遺伝子配列を含むファイルがあります。たとえば、次のようになります。

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です。したがって、これらの行の条件はNFfalseと評価され、効果的にスキップされます。)

答え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
  }
'

関連情報