根据与正则表达式匹配的标头从文件中过滤列

时间:2016-05-18 14:38:30

标签: file awk filter

我有以下文件

foo_foo   bar_blop   baz_N  toto_N    lorem_blop
1          1         0      0         1
1          1         0      0         1

我想删除标题上带有_N标记的列(或选择所有其他标记)

所以输出应该是

foo_foo   bar_blop   lorem_blop
1          1         1
1          1         1

我找到了一些答案,但没有人这样做 我知道awk可以做到这一点,但我不明白如何用这种语言自己做(我不擅长awk)。

感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

 awk 'NR==1{for(i=1;i<=NF;i++)if(!($i~/_N$/)){a[i]=1;m=i}}
 {for(i=1;i<=NF;i++)if(a[i])printf "%s%s",$i,(i==m?RS:FS)}' f|column -t

输出:

foo_foo  bar_blop  lorem_blop
1        1         1
1        1         1

答案 1 :(得分:1)

$ cat tst.awk
NR==1 {
    for (i=1;i<=NF;i++) {
        if ( (tgt == "") || ($i !~ tgt) ) {
            f[++nf] = i
        }
    }
}
{
    for (i=1; i<=nf; i++) {
        printf "%s%s", $(f[i]), (i<nf?OFS:ORS)
    }
}

$ awk -v tgt="_N" -f tst.awk file | column -t
foo_foo  bar_blop  lorem_blop
1        1         1
1        1         1

$ awk -f tst.awk file | column -t
foo_foo  bar_blop  baz_N  toto_N  lorem_blop
1        1         0      0       1
1        1         0      0       1

$ awk -v tgt="blop" -f tst.awk file | column -t
foo_foo  baz_N  toto_N
1        0      0
1        0      0

此与@Kent's solution之间的主要区别在于效果,影响会因您想要在每一行上打印的字段百分比而有所不同。

以上读取文件的第一行时会创建一个要打印的字段数字数组,然后对于输入文件的每一行,它只是在循环中打印这些字段。因此,如果您想要打印100个字段中的3个,那么此脚本将在每个输入行上循环遍历3个迭代/字段。

@ Kent的解决方案还创建了一个要打印的字段编号数组,但是对于输入文件的每一行,它都会访问每个字段以测试它是否在打印之前是否在该数组中。因此,如果您想要打印100个字段中的3个,那么@ Kent的脚本将遍历每个输入行上的所有100个迭代/字段。