【问题标题】:Using awk to get unique values from column 1, and sum corresponding values in column 2?使用 awk 从第 1 列获取唯一值,并对第 2 列中的相应值求和?
【发布时间】:2018-12-25 22:41:34
【问题描述】:

我有一个以下格式的 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 列是 Mbs。对于第 1 列中每次出现的服务器名称,在第 2 列中添加相应的值。所以我留下了一个新表,第 1 列中没有重复项,只有第 2 列中的 Mbs 总和。

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

Server1,TotalMbs 服务器2,总Mbs 服务器3,总Mbs

我知道这可以用 awk 完成,但我不知道如何,我认为传入第 1 列中的值,然后在第 2 列中增加一个计数并继续逐行执行。相当棘手???我的冗长而不优雅的解决方案是在循环中为每个服务器创建一个临时文件,然后为每个文件创建第 2 列,然后在最后 rm 文件,但我知道它可以用 awk 在一个内衬中完成。

【问题讨论】:

  • 请在您的帖子中的代码标签中发布示例输入和示例输出,然后让我们知道。

标签: bash csv awk grep


【解决方案1】:

以下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

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

$ 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. 扫描每一行,在每一列中找到“Server”,如果找到的话,将下一列的值存入a对应的key中,即a[$i]=$(i+1)

【讨论】:

  • 这很有魅力 - 非常感谢!我的朋友用一个 40 行的 python 脚本做到了,但我知道用 awk 是可能的!!!
【解决方案2】:
awk -F',' '{ 
             servers[$1] += $;
           } 
           END {
             for (server in servers) { 
               printf("%s %f\n", server, servers[server]); 
             }
           }'

如果你想在特定的服务器上过滤,你可以在第一个块中添加一个'//'匹配,使它只在匹配条件的行上执行。

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 1970-01-01
    • 2018-11-02
    • 2019-09-12
    • 2019-03-30
    • 2020-01-16
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多