我有一个文本文件temp1,并说它有超过20列,它的数值如下所示,
1,0,3,0,5........,
1,0,5,0,8........,
3,0,6,0,3........,
5,0,6,0,4........,
.................,
我想删除总数(总和)为零的列,我需要将剩余列重定向到新文件
ie:例如,如上面的第2和第4列总共为零,所以我需要删除第2和第4列并将其重定向到单独的文件。
任何人都可以帮我吗?
答案 0 :(得分: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 ""
}
}
答案 1 :(得分: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”。“next”确保我们只在FNR(= CURRENT文件中的行数)== NR(=总行数)时执行此操作,这只在第一次通过时才是真的。
在第二遍(因此我们直接转到第二个{},现在是NR&gt; FNR):我们只显示具有相应$col
的列值wewantthiscolumn(col)==1
,然后是“ ,“(所以有一点问题:最后一个col会有一个”,“之后)
然后我们通过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”来确保我只删除相关字段...但这意味着第一种方式实际上更简单^^:只打印字段你需要,然后摆脱行尾的“,”。
答案 2 :(得分: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
答案 3 :(得分: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