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

时间:2018-07-18 06:14:50

标签: bash csv awk grep

我有以下格式的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,总计Mb Server3,总计Mbs

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

2 个答案:

答案 0 :(得分:0)

以下awk脚本可能会为您提供帮助,

$ 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 "\n"}' input_file
Server3,64.34 Server4,56.89 Server1,54.63 Server2,110.16

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

$ 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 "\n"}' input_file
Server1,54.63 Server2,110.16 Server3,64.34 Server4,56.89

oneliner也可以这样写:

awk -F'[ |,]' '{
    if($i ~ "Server")
      a[$i]+=$(i+1)
} END{
  for(i in a)
    printf "%s,%s ",i,a[i];
  printf "\n"
}' input_file

简要说明,

  1. 将“”和“,”设置为分度数
  2. 扫描每一行,在每一列中找到“服务器”,然后将下一列的值存储到a的相应键中,即找到的a[$i]=$(i+1)中。

答案 1 :(得分:0)

awk -F',' '{ 
             servers[$1] += $;
           } 
           END {
             for (server in servers) { 
               printf("%s %f\n", server, servers[server]); 
             }
           }'

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