同じトピックを削除し、awkの他のすべての行に影響を与える方法

同じトピックを削除し、awkの他のすべての行に影響を与える方法

2つのDNA配列(同じ塩基数を含む)を含むファイルがあります。

>seq1
NNNNNAGAATGGGTGANNATTTCCCNN
>seq2
NNAGGGTCCCAATCCNNAACCTTNNNN

N1つまたは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

を利用すれば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」と表示されます。次に別の転置を実行し、マスクビットを取得し、入力ラスタファイルで作業して目的の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

関連情報