以下格式有一个表格。是否可以使用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查看数据的方式。
答案 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
更改为不太模糊的内容print ""
优于printf "\n"
第二批评论后:
非常感谢校对。自从我上次做了一些严肃的鹰派编程以来已经将近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++ }