← 中文资源

简体中文版本

AWK CSV 列聚合统计

用 awk 单遍聚合 CSV 列:分组数组求和计数、END 块输出报表、条件过滤与聚合一步完成,流式输入零全量驻留。

阅读英文原文

示例说明

awk 是处理分隔文本的原生方案:-F 设分隔符后每行自动拆成 $1 $2 字段,关联数组按任意键聚合——orders[region] 的键是区域字符串,分组逻辑零成本。NR 排除表头是 CSV 的常规处理。END 块在输入耗尽后执行,报表输出与聚合累积天然分离。

技术要点

  • 关联数组按字符串键分组聚合
  • END 块输出与累积阶段分离
  • 条件过滤前置在同一表达式中

代码解读

aggregate 的主块对每行累加三个数组的对应项;END 遍历数组输出各区域的订单、营收与均单价,printf 的格式符对齐列宽;total_orders 独立累计无分组的全局和。第二个管道演示字段抽取接 sort 排序的流水线;第三个把过滤条件直接写进主块,一行代码完成过滤加聚合。

使用建议

含引号内逗号的真实 CSV 需 gawk 的 FPAT 或专门解析器。数字字段要校验非空防字符串拼接。大文件 awk 单遍特性优于反复 sort。

代码示例

#!/usr/bin/env bash
set -euo pipefail

# 输入形态:region,channel,orders,revenue_cents
readonly SAMPLE='eu,web,120,450000
eu,mobile,80,290000
na,web,95,310000
na,mobile,45,150000
apac,web,30,90000'

# 单遍聚合:分组求和与计数
aggregate() {
  awk -F',' '
    NR > 1 {
      orders[$1] += $3
      revenue[$1] += $4
      count[$1] += 1
      total_orders += $3
    }
    END {
      for (region in orders) {
        printf "%-6s 订单 %6d  营收 %10d  均单价 %8.0f\n", \
          region, orders[region], revenue[region], \
          revenue[region] / orders[region]
      }
      printf "TOTAL  订单 %6d\n", total_orders
    }
  '
}

echo "$SAMPLE" | aggregate

# 流式管道形态:配合 sort 输出前 N
echo "$SAMPLE" | awk -F',' 'NR > 1 { print $1, $4 }' \
  | sort -k2,2nr \
  | head -3

# 条件过滤加聚合一步完成
echo "$SAMPLE" | awk -F',' '$3 >= 80 { sum += $4; n++ }
  END { if (n > 0) printf "大渠道合计营收: %d(%d 个)\n", sum, n }'