关于bash:使用awk从第1列获取唯一值,并在第2列中求和相应的值吗?

Using awk to get unique values from column 1, and sum corresponding values in column 2?

我有以下格式的CSV文件,有人告诉我这是"地图缩小问题"
{
服务器1,33.23
服务器2,43.46
服务器3,64.34
服务器4,56.89
服务器2,33.24
服务器1,21.40
服务器2,33.46
}

这是几千行,大约有80个服务器名称在第1列中分别出现几次,而第2列是Mb。对于第1列中每次出现的服务器名称,请在第2列中添加相应的值。因此,我剩下一个新表,第1列中没有重复项,而只有第2列中的Mb总数。

因此,如果我不清楚-对于第1列中每次出现的任何唯一值,请在第2列中添加相应的值。最后,我会得到。

Server1,总计Mbs
Server2,总计Mbs
Server3,总计Mbs

我知道可以用awk完成此操作,但我不知道如何做,我认为传入第1列中的值,然后增加第2列中的计数,并逐行执行。这很棘手???我冗长而优雅的解决方案是在循环中为每台服务器创建一个临时文件,然后为每个文件仅创建第2列,然后在末尾对这些文件进行rm处理,但我知道可以使用awk在一个内衬中完成。


1
2
3
4
5
6
7
8
9
awk -F',' '{
             servers[$1] += $;
           }
           END {
             for (server in servers) {
               printf("%s %f\
", server, servers[server]);
             }
           }'

如果要在特定服务器上进行过滤,可以将" //"匹配项添加到第一个块中,以使其仅在符合条件的行上执行。


以下awk脚本可能会对您有所帮助,

1
2
3
$ awk -F'[ |,]'  '{for(i=1;i<=NF;i++)if($i ~"Server")a[$i]+=$(i+1)}END{for(i in a)printf"%s,%s",i,a[i];printf"\
"}'
input_file
Server3,64.34 Server4,56.89 Server1,54.63 Server2,110.16

如果需要有序输出,请在BIGIN块中添加BEGIN{PROCINFO["sorted_in"]="@ind_str_asc"}

1
2
3
$ awk -F'[ |,]'  'BEGIN{PROCINFO["sorted_in"]="@ind_str_asc"}{for(i=1;i<=NF;i++)if($i ~"Server")a[$i]+=$(i+1)}END{for(i in a)printf"%s,%s",i,a[i];printf"\
"}'
input_file
Server1,54.63 Server2,110.16 Server3,64.34 Server4,56.89

oneliner也可以这样写:

1
2
3
4
5
6
7
8
9
awk -F'[ |,]' '{
    if($i ~"Server")
      a[$i]+=$(i+1)
} END{
  for(i in a)
    printf"%s,%s",i,a[i];
  printf"\
"
}'
input_file

简要说明,

  • 将""和","设置为分度
  • 扫描每一行,在每一列中找到"服务器",然后将下一列的值存储到a的对应键(即a[$i]=$(i+1))中(如果找到的话)。