统计字符串中子串重复的次数

统计字符串中子串重复的次数

我有一个包含基因序列的文件,例如:

ATGTGGATGGTGGGTTACAATGAAGGTGGTGAGTTCAACATGGCTGATTATCCATTCAGTGGAAGGAAACTAAGGCCTCTCATTCCAAGACCAGTCCCAGTCCCTACTACTTCTCCTAACAGCACTTCAACTATAACTCCTTCCTTAAACCGCATTCATGGTGGCAATGATTTATTTTCACAATATCATCACAATCTGCAGCAGCAAGCATCAGTAGGAGATCATAGCAAGAGATCAGAGTTGAATAATAATAATAATCCATCTGCAGCAGTTGTGGTGAGTTCAAGATGGAATCCAACACCAGAACAGTTAAGAGCACTGGAAGAATTGTATAGAAGAGGAACAAGAACACCTTCTGCTGAGCAAATCCAACAAATAACTGCCCAGCTTAGAAAATTTGGAAAAATTGAAGGCAAAAATGTTTTCTATTGGTTTCAGAATCACAAAGCCAGAGAAAGGCAAAAACGACGGCGTCAAATGGAATCAGCAGCTGCTGAGTTTGATTCTGCTATTGAAAAGAAAGACTTAGGCGCAAGTAGG


ACAGTGTTTGAAGTTGAACACACTAAAAACTGGCTACCATCTACAAATTCCAGTACCAGTACTCTTCATCTTGCAGAGGAATCTGTTTCAATTCAAAGGTCAGCAGCAGCAAAAGCAGATGGATGGCTCCAATTCGATGAAGCAGAATTACAGCAAAGAAGAAACTTTATGGAAAGGAATGCCACGTGGCATATGATGCAGTTAACTTCTTCTTGTCCTACAGCTAGCATGTCCACCACAACCACAGTAACAACTAGACTTATGGACCCAAAACTCATCAAGACCCATGAACTCAACTTATTCATTTCACCTCACACATACAAAGAAAGAGAAAACGCTTTTATCCACTTAAATACTAGTAGTACTCATCAAAATGAATCTGATCAAACCCTTCAACTTTTCCCAATAAGGAATGGAGATCATGGATGCACTGATCATCATCATCATCATCATAACATTATCAAAGAGACACAGATATCAGCTTCAGCAATCAATGCACCCAACCAGTTTATTGAGTTTCTTCCCTTGAAAAACTGA

我正在尝试计算上述字符串中“ATG”子字符串的出现次数(只有一行没有换行符)。我的文件包含数十(10s)个这些序列,我希望能够计算出有多少个“ ATG”在每个序列中。每个序列与其他序列之间用空行分隔。

我尝试了 grep 但不知道应该使用哪些选项(如果 grep 可以解决问题)并且我用 google 搜索了任何 awk 示例,但没有找到任何选项。

答案1

ATG返回每行中出现的次数:

awk -F'ATG' 'NF{print NF-1}' testfile

这适用于包含一行或多行的文件。

实施例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为零。因此,这些行上的条件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
  }
'

相关内容