我有一个包含基因序列的文件,例如:
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
}
'