0

我有一个文本文件 temp1 并说它有 20 多列,它的数值如下所示,

1,0,3,0,5........,
1,0,5,0,8........,
3,0,6,0,3........,
5,0,6,0,4........,
.................,

我想删除总和为零的列,我需要将剩余的列重定向到新文件

即:例如上面第 2 列和第 4 列的总数为零,因此我需要删除第 2 列和第 4 列并将其重定向到单独的文件。

有人可以帮我吗?

4

4 回答 4

2
$ cat file
1,0,3,0,5
1,0,5,0,8
3,0,6,0,3
5,0,6,0,4

$ awk -f tst.awk file
1,3,5
1,5,8
3,6,3
5,6,4

$ cat tst.awk
BEGIN{ FS="," }
{
    for (j=1;j<=NF;j++) {
        val[NR,j] = $j
        sum[j] += val[NR,j]
    }
}
END {
    for (i=1;i<=NR;i++) {
        ofs = ""
        for (j=1;j<=NF;j++) {
            if (sum[j]) {
                printf "%s%s",ofs,val[i,j]
                ofs = FS
            }
        }
        print ""
    }
}
于 2013-04-25T15:13:19.563 回答
1

这是使用awk. 像这样运行:

awk -f ./script.awk file{,}

内容script.awk

BEGIN {
    FS=","
}

FNR==NR {
    for(i=1;i<=NF;i++) {
        if ($i != 0) {
            a[i]
        }
    }
    next
}

{
    for(j=1;j<=NF;j++) {
        if (j in a) {
            printf "%s%s", $j, (j==NF ? RS : FS)
        }
    }
}

或者,这是单线:

awk -F, 'FNR==NR { for(i=1;i<=NF;i++) if ($i != 0) a[i]; next } { for(j=1;j<=NF;j++) if (j in a) printf "%s%s", $j, (j==NF ? RS : FS) }' filex{,}

内容file

1,0,3,0,5,0
1,0,5,0,8,1
3,0,6,0,3,2
5,0,6,0,4,5

结果:

1,3,5,0
1,5,8,1
3,6,3,2
5,6,4,5
于 2013-04-25T12:07:54.610 回答
1

您可以使用 awk :(以下内容很难看,但我希望可读。这就是目标。我让更好的 awkist 进一步增强/减少它)

如果数据在文件中/path/to/zefile

awk -F',' '  
      FNR==NR { for (col=1;col<=NF;col++)
                   { if ($col != 0) 
                        {wewantthiscolumn[col]=1 } 
                   }
                next
              }

              { for (col=1;col<=NF;col++) 
                   { if (wewantthiscolumn[col]==1) 
                        { printf ("%s,",$col) } 
                   }
                print "" 
              }' /path/to/zefile /path/to/zefile | sed -e 's/,$//'

这个想法:我们在 /path/to/zefile /path/to/zefile 上启动 awk(因此,它读取了两次)。

在第一遍中,我们创建了一个“wewantthiscolumn”数组。只要该列与 0 不同,该数组就包含“1”。“下一个”确保我们仅在 FNR(=当前文件中的行数)== NR(=总行数)时执行此位,这仅在第一次通过时是正确的。

在第二遍(因此我们直接进入第二个 { } ,因为现在 NR>FNR):我们只显示$col具有对应的列值wewantthiscolumn(col)==1,然后是一个“,”(所以有一个小问题:最后一个列后面会有一个“,”)

然后我们通过 sed 传递它以去掉 ",$" 位。

我不确定有没有更好的方法:awk 可以删除一个字段吗?所以它可以在第二遍删除字段 col 吗?然后打印结果 $0 会容易得多,设置OFS=','为将它们与,...分开

这将使第二次通过:

 awk -F',' '  
      FNR==NR { for (col=1;col<=NF;col++)
                   { if ($col != 0) 
                        {wewantthiscolumn[col]=1 } 
                   }
                next
              }

              { for (col=1;col<=NF;col++) 
                   { if (wewantthiscolumn[col]==0) 
                        $col="DELETETHIS"
                   }
                gensub(",DELETETHIS","",g)
                gensub("DELETETHIS,","",g)
                print $0 
              }' /path/to/zefile /path/to/zefile

我不想假设没有列可以是空的,因此我使用“DELETETHIS”来确保我只删除相关字段......但这意味着第一种方式实际上更简单^^:只打印你需要的字段,然后去掉行尾的“,”。

于 2013-04-25T11:24:36.563 回答
0

使用python的解决方案:

#!/usr/bin/env python

def transpose(grid):
    return zip(*grid)

def removeBlankRows(grid):
    return [list(row) for row in grid if any(map(int,row))]

grid = []
with open("input.csv") as fd:
    for line in fd:
        grid.append(line.strip().split(','))

data = removeBlankRows(transpose(removeBlankRows(transpose(grid))))

for i in data:
    print ",".join(i)

输入:

1,0,3,0,5
1,0,5,0,8
3,0,6,0,3
5,0,6,0,4

输出:

1,3,5
1,5,8
3,6,3
5,6,4

输入:

1,0,3,0,5
1,0,5,0,8
3,0,6,0,3
5,0,6,1,4

输出:

1,3,0,5
1,5,0,8
3,6,0,3
5,6,1,4
于 2013-04-25T12:02:19.967 回答