Bash中awk是否有内置julian day函数?如何为CSV文件追加julian day列
基于Bash+awk实现CSV时间列转换追加的方案
你提出的需求完全可以通过Bash搭配awk落地,先明确原有写法的问题,再给出适配你数据特征的可运行逻辑。
原有写法的核心问题
你尝试的awk '{ jday=date -d(substr($0,2,10)) +%j;print $0","jday }' temp.CMP存在两个会直接导致运行失败的缺陷:
- awk没有内置的“直接将shell命令返回值赋值给变量”的语法,不能像写普通shell脚本一样把命令结果直接赋值给awk变量,必须通过管道结合
getline捕获shell命令的标准输出 - 提取第一列字符串时没有清理首尾的双引号,截取的内容带着引号传给date命令,会直接造成时间解析失败
适配你数据场景的实现逻辑
结合你提供的示例特征(第一列为双引号包裹的时间字符串,存在小时值超过24的累计偏移类非标准时间),实现逻辑完全覆盖你的需求:
- 自动清理第一列的双引号干扰,提取纯时间字符串
- 自动折算跨天偏移、校正超过24的小时值,避免date解析报错中断
- 逐行计算并追加需要的字段:儒略日(年内积日)、年、月、日、时、分
- 完全不改动原有列的内容,新字段统一追加到每行末尾
可直接运行的命令
awk -F, '{ # 清理第一列的双引号 raw_dt = $1 gsub(/"/, "", raw_dt) # 拆分日期、时间部分 split(raw_dt, dt_arr, " ") base_date = dt_arr[1] # 拆分时、分字段 split(dt_arr[2], tm_arr, ":") total_hh = tm_arr[1] + 0 mm = tm_arr[2] + 0 # 折算跨天偏移,校正超24小时的值 day_offset = int(total_hh / 24) real_hh = total_hh % 24 # 拼接为date可识别的标准时间 parse_target = base_date " " sprintf("%02d:%02d:00", real_hh, mm) if (day_offset > 0) parse_target = parse_target " + " day_offset " days" # 调用date批量捕获所有需要的时间字段 cmd = "date -d \"" parse_target "\" +%j,%Y,%m,%d,%H,%M" cmd | getline parsed_result close(cmd) # 按列拆分结果,追加到原行末尾 split(parsed_result, res_arr, ",") print $0 "," res_arr[1] "," res_arr[2] "," res_arr[3] "," res_arr[4] "," res_arr[5] "," res_arr[6] }' temp.CMP > temp_processed.CMP
效果说明
- 自动适配示例中的非标准时间(比如"2021-01-22 24:04:00"),会校正为2021-01-23 00:04的标准时间计算,不会出现解析报错
- 追加列的顺序为儒略日、年、月、日、实际小时、分钟,和你提出的字段提取需求完全匹配
- 整个逻辑可直接嵌入你现有的触发式bash脚本,无额外依赖
性能优化提示
如果待处理文件行数超过10万级,逐行调用date的子进程开销会偏高,此时可以替换为awk内置的日期计算逻辑,直接在awk内部完成儒略日计算和时间拆分,处理速度会有数量级提升。
内容的提问来源于stack exchange,提问作者demailyea
相关产品推荐
相关产品推荐

