동일한 주제를 제거하고 awk의 다른 모든 줄에 영향을 미치는 방법

동일한 주제를 제거하고 awk의 다른 모든 줄에 영향을 미치는 방법

두 개의 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

를 이용하면 awkTwo 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

관련 정보