我有一个包含两个 DNA 序列(具有相同碱基数)的文件:
>seq1
NNNNNAGAATGGGTGANNATTTCCCNN
>seq2
NNAGGGTCCCAATCCNNAACCTTNNNN
N
我想删除一个或两个序列中包含 a 的位置。在此示例中,结果将是:
>seq1
AGAATGGGTGATTTC
>seq2
GTCCCAATCCACCTT
到目前为止,我已经写了,但它只是逐个删除序列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 序列。它的第一行是序列名称,并以符号 开头>
。第二行是 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
上面假设您的输入文件足够小以适合内存。如果没有,您可以通过分两次读取文件来执行相同的操作,第一次创建badPoss[]
,第二次使用它:
$ 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
,您可以使用两遍方法进行如图所示的操作。在第一遍中,我们构建屏蔽位(存储“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”。然后我们再进行一次转置并获得掩码位,然后对输入的 rasta 文件进行操作以获得所需的 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
(所示的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