別のファイルの行を使用して大容量ファイルから列を選択する

別のファイルの行を使用して大容量ファイルから列を選択する

他のファイルの行に基づいて大容量ファイルから列を選択したいと思います。この質問に対する答えはここにありますが、両方の解決策は機能しません。

https://www.biostars.org/p/166527/

データ.TXT

head0 head1 head2 head3 head4  
1 25 1364 22 13  
2 10 215 1 22  

リスト.TXT

head0  
head4 

希望の出力:

head0 head4  
1 13  
2 22

2番目のソリューションの最初のコマンドが機能します。

cat file1.txt | cut -f$(grep -wFf file2.txt TMP | cut -f1 | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/,/g') > OUTPUT cut: option requires an argument -- f

どんな提案がありますか?

ありがとう

ロン

答え1

私のMacでも同じエラーが発生します。

  1. ファイルがタブで区切られていて、先頭または末尾のスペースがないことを確認する必要があります。
  2. sedコマンドは次のように置き換えることができます。paste -sd,
  3. 去る:

    cut -f"$(grep -wFf LIST.TXT TMP | cut -f1 | paste -sd,)" DATA.TXT 
    

しかし、awkソリューションを使用すると、よりきれいでtmpファイルを使用せず、スペースをよりよく許可します。

awk -v OFS='\t' '
    NR == FNR {header[$1] = 1; next}
    FNR == 1 {for (i=1; i<=NF; i++) if ($i in header) column[i] = 1}
    {for (i in column) printf "%s" OFS, $i; print ""}
' headers file

しばらく実行すると、ジョブパイプライン(tmpファイルが必要な白いパイプライン)は次のようになります。

cut -f"$(head -1 DATA.TXT | tr '\t' '\n' | nl | grep -Fwf LIST.TXT | awk '{print $1}' | paste -sd,)" DATA.TXT

答え2

list.txtで定義された順序で列を出力するとします。

$ cat tst.awk
NR==FNR {
    name2out[$1] = ++numOutFlds
    next
}
FNR == 1 {
    for (inFldNr=1; inFldNr<=NF; inFldNr++) {
        outFldNr = name2out[$inFldNr]
        out2in[outFldNr] = inFldNr
    }
}
{
    for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
        inFldNr = out2in[outFldNr]
        printf "%s%s", $inFldNr, (outFldNr < numOutFlds ? OFS : ORS)
    }
}

$ awk -f tst.awk list.txt data.txt
head0 head4
1 13
2 22

関連情報