awkを使用して最後の行と次の行に基づいて12を減算または合計するにはどうすればよいですか?

awkを使用して最後の行と次の行に基づいて12を減算または合計するにはどうすればよいですか?

私は次のデータを持っています:

##sequence-region Q75T13 1 641
Q75T13,UniProtKB,Chain,1,641,.,.,.,ID
Q75T13,UniProtKB,Topological domain,1,60,.,.,.,Note=Cytoplasmic
Q75T13,UniProtKB,Transmembrane,61,85,.,.,.,Note=Helical
Q75T13,UniProtKB,Topological domain,86,641,.,.,.,Note=Lumenal


##sequence-region Q9BRR3 1 403
Q9BRR3,UniProtKB,Chain,1,403,.,.,.,ID
Q9BRR3,UniProtKB,Topological domain,1,22,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Transmembrane,23,43,.,.,.,Note=Helical
Q9BRR3,UniProtKB,Topological domain,44,259,.,.,.,Note=Cytoplasmic

##sequence-region Q96FM1 1 250
Q96FM1,UniProtKB,Topological domain,120,135,.,.,.,Note=Cytoplasmic
Q96FM1,UniProtKB,Transmembrane,136,156,.,.,.,Note=Helical
Q96FM1,UniProtKB,Topological domain,157,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Transmembrane,170,190,.,.,.,Note=Helical
Q96FM1,UniProtKB,Topological domain,191,250,.,.,.,Note=Lumenal

awkコードがどのように見えるか疑問に思います。

lumenalという単語がある行、前の行にtransmembraneという単語がある場合は、列4から-12を引いてlumenalという単語がある行を印刷します。 「lumenal」という単語を含む行の次の行に「transmembrane」という単語が含まれている場合は、列5に+ 12を追加して「lumenal」という単語のある行を印刷します。最終ファイルは次のとおりです。

Q75T13,UniProtKB,Topological domain,74,641,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Topological domain,1,34,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,145,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,157,181,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,179,250,.,.,.,Note=Lumenal

誰でも私を助けることができますか?ちょっと立ち往生しています。 awkとgrepを使用しようとしています。

答え1

次のコマンドを試してください。

root@u2004:~# cat test
##sequence-region Q75T13 1 641
Q75T13,UniProtKB,Chain,1,641,.,.,.,ID
Q75T13,UniProtKB,Topological domain,1,60,.,.,.,Note=Cytoplasmic
Q75T13,UniProtKB,Transmembrane,61,85,.,.,.,Note=Helical
Q75T13,UniProtKB,Topological domain,86,641,.,.,.,Note=Lumenal


##sequence-region Q9BRR3 1 403
Q9BRR3,UniProtKB,Chain,1,403,.,.,.,ID
Q9BRR3,UniProtKB,Topological domain,1,22,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Transmembrane,23,43,.,.,.,Note=Helical
Q9BRR3,UniProtKB,Topological domain,44,259,.,.,.,Note=Cytoplasmic

##sequence-region Q96FM1 1 250
Q96FM1,UniProtKB,Topological domain,120,135,.,.,.,Note=Cytoplasmic
Q96FM1,UniProtKB,Transmembrane,136,156,.,.,.,Note=Helical
Q96FM1,UniProtKB,Topological domain,157,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Transmembrane,170,190,.,.,.,Note=Helical
Q96FM1,UniProtKB,Topological domain,191,250,.,.,.,Note=Lumenal
root@u2004:~# 
root@u2004:~# awk -F, -v OFS=, '{while(1){if($0~/Lumenal/){a=$0; $4-=12;p=$0; $0=a;$5+=12;n=$0; if(index(pre,"Transmembrane")>0)print p; if(getline>0){if(index($0,"Transmembrane"))print n; if($0~/Lumenal/){pre=$0; continue}}} break}} {pre=$0}' test
Q75T13,UniProtKB,Topological domain,74,641,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Topological domain,1,34,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,145,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,157,181,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,179,250,.,.,.,Note=Lumenal
root@u2004:~#

答え2

3行のスクロールバッファを維持し、以下を確認してください。

$ cat tst.awk
BEGIN { FS=OFS="," }
{
    nxt = $0
    prt()
}
END {
    prt()
}

function prt() {
    if ( cur ~ /Lumenal/ ) {
        if ( pre ~ /Transmembrane/ ) {
            $0 = cur
            $4 -= 12
            print
        }

        if ( nxt ~ /Transmembrane/ ) {
            $0 = cur
            $5 += 12
            print
        }
    }

    pre = cur
    cur = nxt
    nxt = ""
}

$ awk -f tst.awk file
Q75T13,UniProtKB,Topological domain,74,641,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Topological domain,1,34,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,145,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,157,181,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,179,250,.,.,.,Note=Lumenal

答え3

列区切り記号をコンマに変更する前に、この問題を解決しました。最初の作業は、テストファイルの複数のスペースをタブに変更することです。

$ cat indata 
##sequence-region Q75T13 1 641
Q75T13  UniProtKB   Chain   1   641 .   .   .   ID
Q75T13  UniProtKB   Topological domain  1   60  .   .   .   Note=Cytoplasmic    
Q75T13  UniProtKB   Transmembrane   61  85  .   .   .   Note=Helical
Q75T13  UniProtKB   Topological domain  86  641 .   .   .   Note=Lumenal


##sequence-region Q9BRR3 1 403
Q9BRR3  UniProtKB   Chain   1   403 .   .   .   ID
Q9BRR3  UniProtKB   Topological domain  1   22  .   .   .   Note=Lumenal
Q9BRR3  UniProtKB   Transmembrane   23  43  .   .   .   Note=Helical
Q9BRR3  UniProtKB   Topological domain  44  259 .   .   .   Note=Cytoplasmic

##sequence-region Q96FM1 1 250
Q96FM1  UniProtKB   Topological domain  120 135 .   .   .   Note=Cytoplasmic
Q96FM1  UniProtKB   Transmembrane   136 156 .   .   .   Note=Helical
Q96FM1  UniProtKB   Topological domain  157 169 .   .   .   Note=Lumenal
Q96FM1  UniProtKB   Transmembrane   170 190 .   .   .   Note=Helical
Q96FM1  UniProtKB   Topological domain  191 250 .   .   .   Note=Lumenal

以下はスクリプトです。関数の3番目のパラメータはsplitタブ文字です。

#!/bin/bash
awk '
        function add12(out_line) {
                iarr = split( out_line, arr, "  " )
                arr[5] = 12 + arr[5]
                printf( "%s", arr[1])
                for (i=2 ; i<=iarr ; i++) printf( "\t%s", arr[i] )
                printf( "\n" )
        }

        function sub12(out_line) {
                iarr = split( out_line, arr, "  " )
                arr[4] = arr[4] - 12
                printf( "%s", arr[1])
                for (i=2 ; i<=iarr ; i++) printf( "\t%s", arr[i] )
                printf( "\n" )
        }

        NR == 1 { last_line = $0 ; next }
        NR == 2 { test_line = $0 ; next }

        test_line ~ /Lumenal/ {
                if (last_line ~ /Transmembrane/) sub12( test_line )
                if ($0  ~ /Transmembrane/) add12( test_line )
        }

        {
                last_line = test_line
                test_line = $0
        }

        END {
                if (test_line ~ /Lumenal/) {
                        if (last_line ~ /Transmembrane/) sub12( test_line )
                }
        }
' $1

そして「証拠はプリンにある」:

$ ./doit indata
Q75T13  UniProtKB   Topological domain  74  641 .   .   .   Note=Lumenal
Q9BRR3  UniProtKB   Topological domain  1   34  .   .   .   Note=Lumenal
Q96FM1  UniProtKB   Topological domain  145 169 .   .   .   Note=Lumenal
Q96FM1  UniProtKB   Topological domain  157 181 .   .   .   Note=Lumenal
Q96FM1  UniProtKB   Topological domain  179 250 .   .   .   Note=Lumenal

私が作ったdoit2

$ diff doit*
4c4
<       iarr = split( out_line, arr, "  " )
---
>       iarr = split( out_line, arr, "," )
7c7
<       for (i=2 ; i<=iarr ; i++) printf( "\t%s", arr[i] )
---
>       for (i=2 ; i<=iarr ; i++) printf( ",%s", arr[i] )
12c12
<       iarr = split( out_line, arr, "  " )
---
>       iarr = split( out_line, arr, "," )
15c15
<       for (i=2 ; i<=iarr ; i++) printf( "\t%s", arr[i] )
---
>       for (i=2 ; i<=iarr ; i++) printf( ",%s", arr[i] )

csvファイルを使用してください。

$ ./doit2 comma
Q75T13,UniProtKB,Topological domain,74,641,.,.,.,Note=Lumenal
Q9BRR3,UniProtKB,Topological domain,1,34,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,145,169,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,157,181,.,.,.,Note=Lumenal
Q96FM1,UniProtKB,Topological domain,179,250,.,.,.,Note=Lumenal

関連情報