使用另一个文件中的行从大文件中选择列

使用另一个文件中的行从大文件中选择列

我想根据另一个文件中的行从一个大文件中选择列。这个问题已在这里得到解答,但这两种解决方案都不起作用。

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 上也出现同样的错误。

  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

相关内容