如何优化Shell脚本,单次读取1500万条CSV文件完成统计提速
解决方案
核心逻辑是先把所有待统计的ID加载到内存做哈希索引,单次遍历大CSV的每一行时匹配ID、同时判断12个条件更新对应计数器,全程只读取1次大文件,3000个ID的计数器内存占用可以忽略不计,1500万行的CSV遍历一般几分钟就能跑完,比原方案的36000次全量扫描效率提升上千倍。
实现方案(awk实现,Shell原生支持无需额外依赖)
- 第一步:先读取IDs_file加载所有待统计ID,同时为每个ID初始化12个条件的计数器为0
- 第二步:遍历大CSV的每一行,先提取行内ID字段,非目标ID直接跳过;命中目标ID则依次判断12个统计条件,符合条件就给对应计数器加1
- 第三步:遍历完成后按指定CSV格式输出所有ID的计数结果
可直接复用的脚本模板
替换脚本内的占位符为你的实际业务参数即可运行:
awk -F ',' ' # 加载待统计ID列表 NR == FNR { ids[$1] = 1 # 初始化12个条件的计数器 for(i=1;i<=12;i++) { count[$1 "_" i] = 0 } next } # 处理大CSV每一行 { # 跳过CSV表头(如果没有表头可以删掉这行) if(FNR == 1) next # 提取当前行的ID字段,此处假设ID在第3列,替换为你实际的ID列序号即可 curr_id = $3 # 非目标ID直接跳过 if (!(curr_id in ids)) next # 替换为你实际的12个条件判断逻辑,示例为条件1对应第2列值大于100的场景 if ($2 > 100) count[curr_id "_1"]++ if (你的条件2判断逻辑) count[curr_id "_2"]++ # 以此类推补充剩下的10个条件 if (你的条件12判断逻辑) count[curr_id "_12"]++ } # 输出结果CSV END { # 输出CSV表头,替换为你实际的列名即可 print "ID,条件1计数,条件2计数,条件3计数,条件4计数,条件5计数,条件6计数,条件7计数,条件8计数,条件9计数,条件10计数,条件11计数,条件12计数" for (id in ids) { printf "%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", \ id, count[id "_1"], count[id "_2"], count[id "_3"], count[id "_4"], count[id "_5"], count[id "_6"], \ count[id "_7"], count[id "_8"], count[id "_9"], count[id "_10"], count[id "_11"], count[id "_12"] } } ' IDs_file 你的大CSV文件路径 > 输出结果.csv
额外优化提示
如果你的CSV字段包含带逗号的引号包裹内容,可先用csvkit的csvcut工具提取需要的ID和条件判断相关字段,再喂给awk处理,避免字段匹配错误。
内容的提问来源于stack exchange,提问作者Raziel
相关产品推荐
相关产品推荐

