2

所以我有一个像这样的laaaaaaaarge文件:

Item|Cost1|Cost2
Pizza|50|25
Sugar|100|100
Spices|100|200
Pizza|100|25
Sugar|200|100
Pizza|50|100

我想为特定项目添加所有Cost1s 和s 并生成合并输出。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
4

3 回答 3

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 {}是我们在阅读整个文件后要做的事情。它包括遍历数组并打印值。
于 2013-09-30T15:19:51.957 回答
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 行。

于 2013-09-30T15:30:16.903 回答
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
于 2013-09-30T15:40:27.423 回答