从制表符分隔文件中搜索和打印特定列?

时间:2015-03-10 03:47:52

标签: bash awk

我可以使用awk从文件中打印第n列; cut命令也可以执行类似的操作..但我需要根据其名称来获取列,例如:

col1 col2 col3 col4
2 5 3 1
6 4 7 1 
3 6 5 9
7 9 7 8

如果我列出列名作为输入:例如col1,col3(将是一个很长的列名列表,所以如果输入可以是一个数组会有帮助)

输出将是

col1 col3
2 3
6 7 
3 5
7 7

有谁知道我怎么可能在bash中这样做?

2 个答案:

答案 0 :(得分:1)

$ awk -v s="col1 col3" 'BEGIN{split(s,v," ");for (i=1;i<=length(v);i++)a[v[i]]=1} NR==1{split($0,b,"\t")} {for (i=1;i<=NF;i++)if (b[i] in a)printf "%s\t",$i;print""}' file
col1    col3
2       3
6       7
3       5
7       7

如何运作

  • -v s="col1 col3"

    定义一个awk变量s,其中包含您要保留的以空格分隔的列列表。

  • BEGIN{split(s,v," ");for (i=1;i<=length(v);i++)a[v[i]]=1}

    创建一个关联数组a,其关键字是列名,其值为字符串s中的列的值。

  • NR==1{split($0,b,"\t")}

    将列名保存在关联数组b中。

  • for (i=1;i<=NF;i++) if (b[i] in a) printf "%s\t",$i; print""

    对于每列i,如果列名b[i]在数组a中,请打印列,然后打印一个标签。

    要完成,print ""会打印换行符。

答案 1 :(得分:1)

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==1 {
    for (i=1;i<=NF;i++) {
        if ( match(cols,"(^| )"$i"( |$)") ) {
            colNrs[++numCols] = i
        }
    }
}
{
    for (i=1;i<=numCols;i++) {
        printf "%s%s", $(colNrs[i]), (i<numCols?OFS:ORS)
    }
}

$ awk -v cols="col1 col3" -f tst.awk file
col1    col3
2       3
6       7
3       5
7       7