根据从其他文件中选择的标头从文件中提取列

时间:2012-06-19 09:31:18

标签: unix awk

我想在awk中解决以下问题。我有一个大的文本表,逗号分隔,由100k行和5k列组成。第一行是标题,第一列是记录标识。然后,我有第二个文本文件,其中包含第一个文件中的标头的子集。我想提取第一个文件的所有列,其标题包含在第二个文件中给出的列表中。这是输入和所需输出的示例:

DATA.TXT

   ID, head1, head2, head3, head4  
    1, 25.5, 1364.0, 22.5, 13.2  
    2, 10.1, 215.56, 1.15, 22.2  

LIST.TXT

head1  
head4  

期望的输出:

ID, head1, head4  
1, 25.5, 13.2  
2, 10.1, 22.2

任何人都可以给我一些关于如何在awk中解决这个问题的建议,或者通过unix脚本来解决这个问题?在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

有一个有用的awk脚本here,可用于从csv文件中提取特定的列名。

我稍微修改了它,以便它可以从另一个文件中读取列名。将下面的脚本保存为dataExtractor.sh

#!/bin/bash

DATAFILE=${1:-data.txt}
COLUMNFILE=${2:-list.txt}

awk -F, -v colsFile="$COLUMNFILE" '
   BEGIN {
     j=1
     while ((getline < colsFile) > 0) {
        col[j++] = $1
     }
     n=j-1;
     close(colsFile)
     for (i=1; i<=n; i++) s[col[i]]=i
   }
   NR==1 {
     for (f=1; f<=NF; f++)
       if ($f in s) c[s[$f]]=f
     next
   }
   { sep=""
     for (f=1; f<=n; f++) {
       printf("%c%s",sep,$c[f])
       sep=FS
     }
     print ""
   }
' "$DATAFILE"

运行它:

$ cat data.txt
ID,head1,head2,head3,head4
1,25.5,1364.0,22.5,13.2
2,10.1,215.56,1.15,22.2

$ cat list.txt
ID
head1
head4

$ dataExtractor.sh data.txt list.txt
1,25.5,13.2
2,10.1,22.2

答案 1 :(得分:3)

我有一个想法,但由于我没有shell编程经验(并且不知道awk),这看起来像是以一种荒谬的方式重新发明了一些轮子:

$ cat DATA.TXT 
ID, head1, head2, head3, head4
1, 25.5, 1364.0, 22.5, 13.2
2, 10.1, 215.56, 1.15, 22.2

$ cat LIST.TXT 
head1
head4

$ cols=($(sed '1!d;s/, /\n/g' DATA.TXT | grep -nf LIST.TXT | sed 's/:.*$//'))

$ cut -d ',' -f 1$(printf ",%s" "${cols[@]}") DATA.TXT 
ID, head1, head4
1, 25.5, 13.2
2, 10.1, 22.2

P.S。我使用了一些关于来自thisthis答案的bash数组的非常基本的想法。