Bash中使用awk进行算术求和计算失败求助
问题分析与解决
你的脚本存在几个核心问题,直接导致累加结果异常:
- Bash不支持原生浮点运算:用Bash普通加法(比如
lsd=$((lsd + day)))只能处理整数,浮点数会被截断,自然得不到正确结果。 - Awk与Bash变量不互通:你在Awk的
BEGIN块里用$day,但Awk无法直接读取Bash的day变量,且BEGIN块在处理输入前执行,没有数据来源,所以$day是空值,累加结果始终为0。 - Awk进程无法持续累加:每次循环调用的Awk都是独立进程,上一次的累加结果不会保留到下一次循环。
- 未将计算结果回传给Bash变量:就算Awk完成了计算,你也没把结果存回Bash的
lsd变量,最后输出的$lsd根本没被赋值。
修正后的脚本方案
推荐两种可行的解决方式:
方式一:用Awk一次性完成提取与累加(效率更高)
不需要循环,让Awk直接扫描XML文件,提取并累加所有目标数值:
awk -v FS='<|>' ' /^<d00[1-7]>/{ days[substr($2,4,1)] = $3 sum += $3 } END{ printf "%.3f\n", sum > "lsd1.txt" # 保存每日数值到对应文件 for(i=1; i<=7; i++){ printf "%.3f\n", days[i] > "day"i".txt" } } ' data.xml
说明:
- 用
<和>作为分隔符,直接提取标签内的数值 - 匹配
d001到d007的标签,同时记录每日数值并累加总和 - 最后将总和和每日数值分别写入对应文件
方式二:保留循环逻辑,用bc处理浮点累加
如果坚持用循环结构,需要借助bc工具实现浮点运算(Bash本身不支持):
lsd=0.000 for i in {1..7}; do day=$(grep -oPm1 "(?<=<d00$i>)[^<]+" data.xml) printf "%.3f" "$day" > "day$i.txt" # 用bc执行浮点加法,保留3位小数 lsd=$(echo "scale=3; $lsd + $day" | bc) done printf "%.3f" "$lsd" > lsd1.txt
说明:
- 初始化
lsd为0.000作为累加起点 - 每次循环用
bc计算累加值,scale=3指定结果保留3位小数 - 将每次的累加结果存回
lsd变量,最后输出到文件
内容的提问来源于stack exchange,提问作者Sabreur
相关产品推荐
相关产品推荐

