如何用Shell实现文本文件列级求和并动态更新总和行
实现文本文件列级数值求和的Shell方案
刚好遇到过类似的需求,下面这个Shell脚本可以完美解决你的问题——不管是给初始文件添加总和行,还是后续新增数据列后更新总和,都能自动处理:
通用脚本实现
#!/bin/bash # 替换成你的目标文件路径 input_file="data.txt" # 先清理旧的Total行(如果最后一行是Total开头的话) sed -i '$ {/^Total/d}' "$input_file" # 用awk计算各列总和并追加新的Total行 awk ' NR == 1 { # 保存表头并初始化总和数组 header = $0 for (i=2; i<=NF; i++) { sum[i] = 0 } print header next } { # 逐行累加数值列的总和 for (i=2; i<=NF; i++) { sum[i] += $i } print $0 } END { # 输出Total行 printf "Total" for (i=2; i<=NF; i++) { printf " %d", sum[i] } printf "\n" }' "$input_file" > temp.txt && mv temp.txt "$input_file"
脚本工作原理
- 清理旧总和行:用
sed检查文件最后一行,如果是以Total开头的旧总和记录,直接删除,避免重复累加。 - 表头处理:awk读取第一行表头时,初始化对应数值列的总和数组。
- 逐行累加:遍历每一行数据,把第二列及以后的数值列逐个累加到总和数组中。
- 生成新总和行:处理完所有数据后,输出
Total开头的新行,后面跟着各数值列的最终总和。 - 替换原文件:把处理后的内容写入临时文件,再替换原文件,保证原子性。
使用示例
初始文件处理
假设你的初始文件data.txt内容如下:
name usersToday usersTommorrow Data1 92 181 DataTwo 5 7 Something 61 73 Something_with_long_name 0 0
给脚本加执行权限:
chmod +x sum_columns.sh
运行脚本后,文件会变成:
name usersToday usersTommorrow Data1 92 181 DataTwo 5 7 Something 61 73 Something_with_long_name 0 0 Total 158 262
新增列后更新总和
第二天新增day2列后,文件内容变为:
name usersToday usersTommorrow day2 Data1 92 181 10 DataTwo 5 7 20 Something 61 73 30 Something_with_long_name 0 0 40 Total 158 262
再次运行脚本,旧的Total行被删除,新的总和行自动计算所有列的总和:
name usersToday usersTommorrow day2 Data1 92 181 10 DataTwo 5 7 20 Something 61 73 30 Something_with_long_name 0 0 40 Total 158 262 100
额外说明
- 如果你的数值列包含浮点数,只需要把awk中的
%d改成%.2f(保留两位小数)即可,awk默认支持浮点运算。 - 脚本使用临时文件避免直接修改原文件时的异常,如果你担心临时文件冲突,可以把
temp.txt改成/tmp/temp_sum_$$.txt(用进程ID做后缀)。 - 不管文件新增多少列,脚本都会自动识别所有数值列并计算总和,完全不需要修改脚本逻辑。
内容的提问来源于stack exchange,提问作者dynamicJos
相关产品推荐
相关产品推荐

