2つのDNA配列(同じ塩基数を含む)を含むファイルがあります。
>seq1
NNNNNAGAATGGGTGANNATTTCCCNN
>seq2
NNAGGGTCCCAATCCNNAACCTTNNNN
N
1つまたは2つのシーケンスからaを含む位置を削除したいと思います。この例では、結果は次のようになります。
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
これまでに書いてきましたが、シーケンスを1つずつ削除しましたN
。
awk '/^>/ {printf("%s%s\t",(N>0?"\n":""),$0);N++;next;} {printf("%s",$0);} END {printf("\n");}' < input | sed 's/N//g' | tr "\t" "\n" > output
これを行う方法を知っている人はいますか?
生物学的背景:FASTAフォーマットは、テキストファイルにDNA配列を作成する方法を設計します。最初の行は記号で始まるシーケンス名です>
。 2行目はDNA配列そのものです。私の場合は2つのシーケンスがあるので、4つの行があります。
答え1
簡単な方法は次のとおりです。
#!/bin/sh
awk '
function strip( n ) {
i = index(body[n], "N")
while ( i > 0 ) {
body[1] = substr(body[1], 0, i-1) substr(body[1], i+1)
body[2] = substr(body[2], 0, i-1) substr(body[2], i+1)
i = index(body[n], "N")
}
}
/^>/ {
N++
label[N] = $0
next
}
{
body[N] = $0
}
END {
if ( N != 2 ) {
print "Incorrect number of entries" >"/dev/stderr"
exit 1
}
strip(1)
strip(2)
print label[1]
print body[1]
print label[2]
print body[2]
}
' dna >output
ファイルDNAは次のとおりです。
>seq1
NNNNNAGAATGGGTGANNATTTCCCNN
>seq2
NNAGGGTCCCAATCCNNAACCTTNNNN
ファイル出力は次のとおりです。
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
私はこれがあなたの要件を満たしていると思います。
答え2
$ cat tst.awk
{ lines[NR] = $0 }
!/>/ {
numChars = length($0)
for ( charPos=1; charPos<=numChars; charPos++) {
char = substr($0,charPos,1)
if ( char == "N" ) {
badPoss[charPos]
}
}
}
END {
for ( lineNr=1; lineNr<=NR; lineNr++ ) {
line = lines[lineNr]
if ( line ~ />/ ) {
out = line
}
else {
out = ""
numChars = length(line)
for ( charPos=1; charPos<=numChars; charPos++) {
if ( !(charPos in badPoss) ) {
char = substr(line,charPos,1)
out = out char
}
}
}
print out
}
}
$ awk -f tst.awk file
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
上記は、入力ファイルがメモリに入るのと同じくらい小さいと仮定しています。そうでない場合は、ファイルを2回読み取って同じ操作を実行できます。まず、ファイルを作成してbadPoss[]
2番目に使用します。
$ cat tst.awk
NR==FNR {
if ( !/>/ ) {
numChars = length($0)
for ( charPos=1; charPos<=numChars; charPos++) {
char = substr($0,charPos,1)
if ( char == "N" ) {
badPoss[charPos]
}
}
}
next
}
{
if ( />/ ) {
out = $0
}
else {
out = ""
numChars = length($0)
for ( charPos=1; charPos<=numChars; charPos++) {
if ( !(charPos in badPoss) ) {
char = substr($0,charPos,1)
out = out char
}
}
}
print out
}
$ awk -f tst.awk file file
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
答え3
を利用すればawk
Two Pass方式を用いて図のようにすることができる。最初のステップでは、マスクビット(「N」を格納するビット)を作成します。
awk -v OFS= -v _PASS1_=1 '
_PASS1_ {
if ( /^>/ ) next
if (n in a)
for (i=1; i<=n; i++)
a[i] *= substr($0,i,1) != "N"
else {
t=$0
gsub(/N/,0,t)
gsub(/[^0]/,1,t)
gsub(/./,"&"FS,t)
n=split(t,a)
}
next
}
!/^>/{
t=$0; $0=""
for (i=1; i<=n; i++)
$i = a[i] ? substr(t,i,1) : ""
}1
' file _PASS1_=0 file
もう一つの方法は、入力ファイルを置き換えることです。転置された行のどこにも「N」がある場合、その行は「0」と表示され、それ以外の場合は「1」と表示されます。次に別の転置を実行し、マスクビットを取得し、入力ラスタファイルで作業して目的のo / pを取得します。
これはGNU sed+BSD rs+awk
。
rs
転置のためのリシェイパーユーティリティです。
sed -n '/^>/!s/./& /pg' file |
rs -T |
sed '/N/s/.*/0/;t;c 1' |
rs -T |
awk -v OFS= '
NR==1{n=1+split($0,a);next}
!/^>/{
t=$0
for (i=$0=""; ++i in a;)
$i = substr(t, a[i] ? i:n, 1)
}1' - file
出力:-
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
答え4
コードsed
(図を参照)を使用して、2つのステップでこれを実行できます。GNU sed
sed -E '
/\n/{
s///;$q;h;d
}
/^>/{
N;s/.*\n//
y/ATCGN/11110/
G
s/(.*).$/&\1/
/^(.*)\n\1$/{s/$/\n/;D;}
s/^/\n/;ta
:a;/\n$/D
s/\n0(.*)\n1/0\n\10\n/;ta
s/\n.(.*)\n(.)/1\n\1\2\n/;ta
}' file |
sed -E '
1{h;d;}
/^>/b
G;s/^/\n/
:mask
s/\n.(.*)\n0/\n\1\n/
s/\n(.)(.*)\n1/\1\n\2\n/
s/\n\n$//
tmask
' - file