awk同站点相邻行$4字段求和(48h降水量)问题求助
解决AWK计算站点48小时降水量的异常问题
问题背景
现有1500个站点的气象数据文件,已按站点($2字段)和日期排序,其中$4为站点日降水量。需求是:仅当当前行与上一行的$2站点相同时,将两行的$4求和得到48小时降水量;若站点切换,则输出N/A。
现有AWK代码存在以下异常:
- 部分同站点的相邻行未执行求和操作
- 输出中$4字段莫名为空
- 未正确识别站点切换,跨站点的行错误执行了求和
现有异常代码
awk '{ if (prev_station == $2) { sum = prev_rain + $4 print $0, sum } else { print $0, "N/A" } prev_station = $2 prev_rain = $4 }' input.txt
输入输出示例
输入片段(按站点、日期排序)
20230101 001 08 10.5 20230102 001 08 15.2 20230103 001 08 8.7 20230101 002 08 5.3 20230102 002 08 0.0
错误输出片段
20230101 001 08 10.5 N/A 20230102 001 08 25.7 # $4字段为空,求和结果异常 20230103 001 08 8.7 23.9 20230101 002 08 5.3 14.0 # 跨站点错误求和 20230102 002 08 0.0 5.3
期望输出
20230101 001 08 10.5 N/A 20230102 001 08 15.2 25.7 20230103 001 08 8.7 23.9 20230101 002 08 5.3 N/A 20230102 002 08 0.0 5.3
修正后的代码及解释
问题根源
- 未初始化
prev_station,第一行无前置数据时会触发错误判断 - 未处理$4为空或非数值的情况,导致计算时出现异常
- 输出逻辑可能隐含字段丢失(原代码未明确保留$4)
修正代码
awk ' BEGIN { prev_station = "" # 初始化站点变量,避免第一行误判 prev_rain = 0 # 初始化降水量变量 } { # 校验$4是否为有效数值,无效则设为0 curr_rain = ($4 ~ /^[0-9.]+$/) ? $4 : 0 if (prev_station != "" && prev_station == $2) { # 同站点且非第一行,计算48小时降水量 sum_48h = prev_rain + curr_rain print $0, sum_48h } else { # 站点切换或第一行,输出N/A print $0, "N/A" } # 更新上一行数据 prev_station = $2 prev_rain = curr_rain }' input.txt
代码说明
- 初始化变量:
BEGIN块中初始化prev_station为空字符串,确保第一行不会触发求和逻辑 - 字段校验:用正则判断$4是否为有效数值,避免空值/非数值导致的计算异常
- 严格站点判断:仅当存在前置站点且与当前站点相同时才求和,彻底避免跨站点错误计算
- 保留原始数据:直接打印
$0确保原始字段完整输出,解决$4为空的问题
内容的提问来源于stack exchange,提问作者anlom
相关产品推荐
相关产品推荐

