最初の行で、部分文字列に一致するタブで区切られた列を削除します。

最初の行で、部分文字列に一致するタブで区切られた列を削除します。

タイトル(最初の行)に「_HET」文字列を含むテキストファイルから、タブで区切られたすべての列を削除したいと思います。入力テキストファイルは次のとおりです。

rs36810213_HET   rs2438689   rs70927523570_HET   rs54666437   ...
1                0           2                   0
0                1           0                   1
2                0           1                   1
...              ...         ...                 ...

出力テキストファイルは次のようにする必要があります。

rs2438689   rs54666437   ...
0           0
1           1
0           1
...         ...

私が使用しているコードは何も削除しません。

#!/bin/bash

path="/data/folder"

awk -v OFS='\t' '

NR==1{
    for (i=1;i<=NF;i++)
        if ($i=="_HET") {
            n=i-1
            m=NF-(i==NF)
        }
    }

{
    for(i=1;i<=NF;i+=1+(i==n))
        printf "%s%s",$i,i==m?ORS:OFS
}

' $path/input.txt >> $path/output.txt

このコードを修正する方法に関する提案はありますか?ありがとうございます!

答え1

awk -F '\t' -f script.awk file

script.awkどこ

BEGIN { OFS = FS }

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i !~ /_HET/)
            keep[i] = 1
}

{
    nf = split($0, fields, FS)
    $0 = ""
    j = 0

    for (i = 1; i <= nf; ++i)
        if (i in keep)
            $(++j) = fields[i]

    print
}

keepまず、最初の行のヘッダーを解析し、連想配列に保持したいヘッダーを覚えておいてください。

次に、各行に対して保持するフィールドでのみ現在のレコード(行)を再作成して印刷します。

現在のフィールド区切り文字の行を配列に(再)分割し、空にしてfieldsこれを行います。みんなフィールド(を使用すると$0 = ""リセットされますNF)を選択し、最後に配列のキーであるフィールドfieldsのみを割り当てますkeep

一部の人々は気の利いた言葉をするのが好きです。

awk -F '\t' -v OFS='\t' 'FNR==1{for(i=1;i<=NF;++i)if($i!~/_HET/)k[i]=1}{n=split($0,f,FS);$0=j="";for(i=1;i<=n;++i)if(i in k)$(++j)=f[i]}1' file

あなたのコードに正確に従わなかったが、:thフィールドを文字列と比較します$i=="_HET"。このフィールドの値i_HET正確に _HET(あなたのタイトルフィールドはありません。)


まったく異なるアプローチ:

cut -f "$( awk -F '\t' -v OFS="," '{for(i=1;i<=NF;++i)if($i!~/_HET/)k[i]=1;$0="";for(i in k)$(++j)=i;print;exit}' file )" file

このawk申請書

BEGIN { OFS = "," }

{
    for (i = 1; i <= NF; ++i)
        if ($i !~ /_HET/)
            keep[i] = 1

    $0 = ""

    for (i in keep)
        $(++j) = i

    print
    exit
}

出力なしコンテンツ必要な列数ですが、対応する列番号をカンマ区切りの文字列として出力します。その後、この文字列はcutデータから列を削除するために使用されます。

答え2

Perlを使用すると、次のようにこれを実行できます。

$ perl -F'/\t/' -pale '$"="\t";
    $. == 1 and @A = grep { $F[$_] !~ /_HET/ } 0 .. $#F;
    $_ = "@F[@A]";
' input.tsv

関連情報