在逗号分隔文件

时间:2016-07-11 04:33:37

标签: unix awk

我有一个包含多个以逗号分隔的列的文件,包括第一列中的客户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。

3 个答案:

答案 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