用于表格式化的awk解决方案

时间:2014-01-02 01:10:06

标签: arrays bash shell unix awk

以下格式有一个表格。是否可以使用AWK脚本来格式化表格,以排除仅包含数字“1”的列?

ST L1 L2 L3 L4 L5
ST2 1 1 1 1 1
ST2 1 0 1 0 1
ST3 1 0 1 0 1
ST3 0 0 1 1 1
ST4 1 0 1 0 1
ST5 1 0 1 0 1
ST6 1 0 1 0 1
ST7 0 0 1 1 1
ST8 0 0 1 0 1
ST9 1 0 1 0 1

输出应如下:

ST L1 L2 L4
ST2 1 1 1
ST2 1 0 0
ST3 1 0 0
ST3 0 0 1
ST4 1 0 0
ST5 1 0 0
ST6 1 0 0
ST7 0 0 1
ST8 0 0 0
ST9 1 0 0

我可以理解列应该如何打印的逻辑,就像在结束块中NR的值一样,如果它等于每次找到1时应该递增的变量,对于给定的列(标题NR == 1和列$ 1除外),打印列。我的麻烦在于实际上尝试打印结束块中的列,因为我正在尝试使用数组,我仍然在学习AWK和数组。我确信有一些聪明的方法可以做到这一点虽然没有使用数组,只是改变了AWK查看数据的方式。

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题:

    {
        # store current line
        line[FNR] = $0

        if (FNR > 1) # skip header
        {
            # select columns
            for (i = 1 ; i <= NF ; i++)
            {
                if ($i != 1) selected[i] = 1
            }
        }
    }

END {
        for (li = 1 ; li <= FNR ; li++)
        {
            # parse current line
            $0 = line[li]

            # pick selected fields
            for (i = j = 1 ; i <= NF ; i++)
            {
                if (selected[i]) $(j++) = $i
            }

            # trim record to selection
            NF = j-1
            print
        }
    }

在Ed Morton的评论之后:

  • l更改为不太模糊的内容
  • printf确实是一个声明,但添加括号也不会受到伤害,或者会不会呢?
  • 同意print ""优于printf "\n"
  • 分号是可选的,但不会受到伤害。对于看起来像C
  • 的东西,我感觉更舒服
  • NR是一个被忽视的错字(因为它通过纯粹的运气产生了预期的输出)。我的意思是NF。
  • 更改了逻辑,以便不添加尾随空白(并且不再使用printf)

第二批评论后:

  • 更改了输出记录的生成,以避免无关的分隔符。

非常感谢校对。自从我上次做了一些严肃的鹰派编程以来已经将近15年了,而且生锈已经黯然失色了。

答案 1 :(得分:2)

awk '
NR==FNR {
    if (NR > 1) {
        for (i=1;i<=NF;i++) {
            if ($i != 1) {
                nonOnes[i]
            }
        }
    }
    next
}
{
    ofs=""
    for (i=1;i<=NF;i++) {
        if (i in nonOnes) {
            printf "%s%s", ofs, $i
            ofs=OFS
        }
    }
    print ""
}
' file file
ST L1 L2 L4
ST2 1 1 1
ST2 1 0 0
ST3 1 0 0
ST3 0 0 1
ST4 1 0 0
ST5 1 0 0
ST6 1 0 0
ST7 0 0 1
ST8 0 0 0
ST9 1 0 0

如果您不想在命令行上两次列出同一文件,可以调整以添加此BEGIN部分:

BEGIN { ARGV[ARGC] = ARGV[ARGC-1]; ARGC++ }