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) }'
1行に1つずつ分数のみを提供するバリアント:
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
サンディップが提案した
sed 'y/ATCG/1234/;s/./+&/2g' file | bc
これは私の最後のものの短い変形です。
まず、コマンドを使用して文字をその数に変更し、y
各文字(2番目の文字から始まる)を前の文字自体に置き換えて、入力文字列の+
出力を ACCA
取得します。その後、この算術式を評価するために使用されます。1+3+3+1
bc
sed
彼のソリューションは、標準がsed
getとas replacementフラグの両方を好まないため、GNUでのみ機能します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