我有一个包含多个以逗号分隔的列的文件,包括第一列中的客户ID。 一个客户ID可能出现在多行上,但始终指的是同一个真实客户。
如何在基于此ID列的shell脚本中运行基本计算?例如,计算给定客户ID的里程总和(第5个字段)。
102,305,Jin,Kerala,40
104,308,Paul,US,45
105,350,Nina,AUS,50
102,390,Jin,Kerala,10
104,395,Paul,US,35
102,399,Jin,Kerala,35
第5个字段是里程,第1个字段是客户ID。
答案 0 :(得分:0)
您可以使用类似的方式获取唯一ID列表(假设第一列是ID):
awk '{print $1}' inputFile | sort -u
这将输出输入文件inputFile
中每一行的第一个字段,对它们进行排序并删除重复项。
然后,您可以将该方法与bash
循环一起使用,以使用另一个awk
命令处理每个唯一ID,以对它们执行某些操作。在下面的代码段中,我打印出每个ID的匹配行:
for id in $(awk '{print $1}' inputFile | sort -u) ; do
echo "${id}:"
awk -vid=${id} '$1==id {print " "$0)' inputFile
done
在该代码中,对于每个单独的ID,它首先输出ID,然后使用awk
仅处理与该ID匹配的行。执行的操作是输出带缩进的整行。
当然,您可以使用与每个ID匹配的行执行任何操作。如下所示,更符合您要求的示例。
首先,这是我用于测试的输入文件 - 我们可以假设字段1是客户ID,字段2是里程:
$ cat inputFile
a 1
b 2
c 3
a 4
b 5
c 6
a 7
b 8
c 9
b 10
c 11
c 12
这是所提方法的命令行记录(注意$
和+
分别是输入提示和延续提示,它们不是实际命令的一部分):
$ for id in $(awk '{print $1}' inputFile | sort -u) ; do
+ awk -vid=${id} '
+ $1==id {print $0; sum += $2 }
+ END {print "Total: "sum; print }
+ ' inputFile
+ done
a 1
a 4
a 7
Total: 12
b 2
b 5
b 8
b 10
Total: 25
c 3
c 6
c 9
c 11
c 12
Total: 41
请记住,对于非大型数据集,也可以在单个awk
脚本中执行此操作,使用关联数组存储总计,然后输出{{1}中的所有数据阻止。我自己倾向于自己更喜欢多次通过方法,因为它最大限度地减少了内存不足的可能性。当然,权衡的是,由于您不止一次处理文件,因此无疑需要更长的时间。
对于单程解决方案,您可以使用以下内容:
END
给你:
$ awk '{sum[$1] += $2} {for (key in sum) { print key": "sum[key]}}' inputFile
答案 1 :(得分:0)
这是一个简单的awk
脚本,它将总结里程并打印客户ID以及最后的总和:
#!/usr/bin/awk -f
BEGIN { FS = "," }
{
customer_id = $1;
mileage = $5;
total_mileage[customer_id] += mileage;
}
END {
for (customer_id in total_mileage) {
print customer_id, total_mileage[customer_id];
}
}
运行(使用chmod +x script.awk
使其可执行后):
$ ./script.awk data.in
102 85
104 80
105 50
或者,作为“一线”:
$ awk -F, '{t[$1]+=$5} END {for (c in t){print c,t[c]}}' data.in
102 85
104 80
105 50
答案 2 :(得分:0)
虽然我同意@wilx使用数据库可能更聪明,但这个示例awk
脚本可以帮助您入门:
awk -v FS=',' '{miles[$1] += $5}
END { for (customerid in miles) {
print customerid, miles[customerid]; } }' customers