他のファイルの行に基づいて大容量ファイルから列を選択したいと思います。この質問に対する答えはここにありますが、両方の解決策は機能しません。
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でも同じエラーが発生します。
- ファイルがタブで区切られていて、先頭または末尾のスペースがないことを確認する必要があります。
- sedコマンドは次のように置き換えることができます。
paste -sd,
去る:
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