タイトル(最初の行)に「_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