두 개의 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
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"로 표시됩니다. 그런 다음 또 다른 전치를 수행하고 마스크 비트를 얻은 다음 입력 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