所以我有一个像这样的 laaaaaaaarge 文件:
Item|Cost1|Cost2
Pizza|50|25
Sugar|100|100
Spices|100|200
Pizza|100|25
Sugar|200|100
Pizza|50|100
我想为特定项添加所有Cost1
和Cost2
并生成合并输出。
我已经编写了一个python代码来执行此操作,
item_dict = {}
for line in file:
fields = line.split('|')
item = fields[0]
cost1 = fields[1]
cost2 = fields[2]
if item_dict.has_key(item):
item_dict[item][0] += int(cost1)
item_dict[item][1] += int(cost2)
else:
item_dict[item] = [int(cost1),int(cost2)]
for key, val in item_dict.items():
print key,"|".join(val)
无论如何,在awk或使用任何其他魔法时,是否有效率和快速地执行此操作?
或者我可以让我的python更优雅,更快?
预期输出
Pizza|200|150
Sugar|300|200
Spices|100|200
答案 0 :(得分:10)
像这样......
$ awk 'BEGIN{OFS=FS="|"}
NR>1 {cost1[$1]+=$2; cost2[$1]+=$3}
END{ for (i in cost1) print i, cost1[i], cost2[i]}' file
Sugar|300|200
Spices|100|200
Pizza|200|150
BEGIN{OFS=FS="|"}
将(输入和输出)字段分隔符设置为|
。NR>1
表示我们将对大于1的行号执行某些操作。这样我们就会跳过标题。cost1
和cost2
是数组,其索引是第一个字段,其值是该点之前的总和。END {}
是我们在阅读完整个文件后所做的事情。它包括循环遍历数组并打印值。答案 1 :(得分:4)
awk '
BEGIN { FS=OFS="|" }
NR==1 { expectedNF = NF; next }
NF != expectedNF { print "Fix your #%@#&! data, idiot!"; exit 1 }'
{
items[$1]
for (c=2;c<=NF;c++)
cost[$1,c] += $c
}
END {
for (i in items) {
printf "%s", i
for (c=2;c<=NF;c++)
printf "%s%s", OFS, cost[i,c]
print ""
}
}
' file
您可以根据需要随意将其压缩为1或2行。
答案 2 :(得分:1)
在实践中,我会做 fedorqui 所做的事情。但是,为了完整起见,此python
脚本应该比原始脚本更快:
#!/usr/bin/env python
import fileinput
item_dict = {}
for line in fileinput.input():
if not fileinput.isfirstline():
fields = line.strip().split('|')
item = fields[0]
cost1 = int(fields[1])
cost2 = int(fields[2])
try:
item_dict[item][0] += cost1
item_dict[item][1] += cost2
except KeyError:
item_dict[item] = [cost1, cost2]
for key, val in item_dict.items():
print "%s|%s|%s" % (key,val[0],val[1])
将脚本保存到sumcols
等文件中并使其可执行chmod +x sumcols
并运行如下:
$ ./sumcols file
Spices|100|200
Sugar|300|200
Pizza|200|150