为列数不固定的表格添加分数列的Shell脚本优化方案
优化CSV数据匹配脚本(大数据量场景)
需求背景
现有两个CSV文件:
- 1.csv:存储姓名与分数的对应关系,格式如下:
name,score Alice,6 Bob,1 Joe,2 John,7 Michel,9
- 2.csv:列数不固定的姓名表格(列数可为1、2、3等),格式如下:
Alice, Bob, Michel, Joe,John
需要实现的效果:在2.csv的每个姓名右侧添加对应的分数列,期望输出:
Alice,6,Bob,1 Michel,9 Joe,2,John,7
现有脚本问题
此前尝试的Shell脚本在小数据量下可正常运行,但处理大数据量时性能失效,脚本代码如下:
#!/bin/bash declare -A scores while IFS=',' read -r name score do scores["$name"]=$score done < 1.csv while IFS=',' read -r -a names do for name in "${names[@]}" do name=$(echo "$name" | xargs) echo -n "$name,${scores[$name]}," done echo done < 2.csv
优化方案(AWK实现)
AWK专为文本结构化数据处理设计,无需依赖Shell循环和外部子进程调用,执行效率远高于原生Shell脚本,适合大数据量场景:
#!/usr/bin/awk -f # 处理第一个文件1.csv,构建姓名-分数映射字典 NR == FNR { # 跳过表头行 if (NR == 1) next # 提取并清理姓名(去除前后空格) name = $0 sub(/^[[:space:]]*/, "", name) sub(/[[:space:]]*,.*$/, "", name) # 提取并清理分数 score = $0 sub(/^.*,/, "", score) sub(/[[:space:]]*$/, "", score) scores[name] = score next } # 处理第二个文件2.csv { # 按逗号分割当前行所有字段 n = split($0, fields, /,/) output = "" for (i = 1; i <= n; i++) { # 清理姓名字段的所有空格 name = fields[i] gsub(/[[:space:]]+/, "", name) # 非空姓名才拼接输出内容 if (name != "") { output = output (output != "" ? "," : "") name "," scores[name] } } # 打印处理后的行 print output }
使用步骤
- 将上述代码保存为
map_score.awk - 赋予执行权限:
chmod +x map_score.awk - 运行脚本:
./map_score.awk 1.csv 2.csv
性能优势说明
- 避免了Shell脚本中频繁的子进程调用(如
echo "$name" | xargs会反复创建子进程,大数据量下严重拖慢速度) - AWK内置函数为原生实现,处理速度远快于Shell循环
- 内存使用更高效,姓名-分数映射直接在AWK内存中处理,无Shell关联数组的额外开销
内容的提问来源于stack exchange,提问作者user15181
相关产品推荐
相关产品推荐

