我想根据另一个文件中的行从一个大文件中选择列。这个问题已在这里得到解答,但这两种解决方案都不起作用。
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
第二个解决方案的第一个命令有效。
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