我想对 DNA 序列进行评分
A = 1 T = 2 C = 3 G = 4
我的输入是
ATGGCGATTGA
AGCTTAGCCAG
AGCTTAGGGAA
我的输出应该是
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27
编辑了我的输入是 .txt 文件
答案1
sed -e 's/A/./g' -e 's/T/../g' \
-e 's/C/.../g' -e 's/G/..../g' file |
awk '{ printf("seq_number %d has score = %d\n", NR, length) }'
输出:
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27
该sed
命令将每个碱基替换为代表分数的多个点。该awk
命令打印到目前为止已读取的行数,并计算该行的长度,即该行的总分。
第一个sed
表达式s/A/./g
,实际上并不需要结果正确。
变化(稍微短一点,只是为了好玩):
sed -e 's/G/TT/g;s/C/TA/g;s/T/AA/g' file |
awk '{ printf("seq_number %d has score = %d\n", NR, length) }'
仅给出分数的变体,每行一个:
tr 'ATCG' '1234' <file | awk -F'\0' -vOFS="+" '$1=$1' | bc
首先将每个字母替换为该字母的分数数字,然后使用 ,在每个数字之间awk
插入。+
然后由 处理每行总分的计算bc
。
最后,是最后一个的变体,但只有 和sed
(bc
同样,只打印分数):
sed 'y/ATCG/1234/;s/\(.\)/+\1/g;s/^+//' file | bc
Sundeep 提出了
sed 'y/ATCG/1234/;s/./+&/2g' file | bc
这是我最后一件事的较短变体。
它首先使用命令将字母更改为相应的数字y
,然后将每个字符(从第二个字符开始)替换为前面加上 的字符本身+
,因此对于输入字符串,ACCA
您将得到1+3+3+1
输出。 bc
然后用于计算该算术表达式。
他的解决方案仅在 GNU 中有效,sed
因为标准sed
不喜欢同时获取和 作为替换标志2
。g
答案2
一个简单的 awk 脚本就可以做到这一点:
得分.awk
BEGIN {
values["A"]=1
values["T"]=2
values["C"]=3
values["G"]=4
}
{
split($0, letters, "");
sum=0;
for (letter in letters)
sum += values[letters[letter]];
print "seq_number", NR, "has score =", sum;
}
当运行您的示例数据时,我得到:
$ awk -f score.awk < input
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27
答案3
好吧,既然这个问题无论如何都得到了解答,这里有一些perl/ruby
俏皮话
$ perl -MList::Util=sum0 -lne 'print "seq_number $. has score = ", sum0 split //, tr/ATCG/1234/r' ip.txt
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27
$ ruby -ne 'puts "seq_number #{$.} has score = #{$_.tr("ATCG", "1234").chars.sum(&:to_i)}"' ip.txt
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27
这个想法是相同的,只要字母转换为单位数字就适用
- 所以,首先使用
tr
更改ATCG
为相应的1234
- 然后按字符拆分字符串,并对数字求和
以及awk
使用返回值的版本split
$ awk 'BEGIN{a["A"]=1; a["T"]=2; a["C"]=3; a["G"]=4}
{score = 0; for(k in a) score += (split($0, n, k)-1)*a[k];
print "seq_number " NR " has score = " score}' ip.txt
seq_number 1 has score = 28
seq_number 2 has score = 28
seq_number 3 has score = 27