You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本实现字母数字日期转数字格式问题求助

问题:转换特殊格式时间数据为标准CSV文件

我有一个每10分钟记录一次的数据文件,日期采用字母数字格式,示例如下:

00 hour 00 minute (00:00H)
00 hour 10 minute (00:10H)
00 hour 20 minute (00:20H)
and so on

输入文件ifile.txt内容:

00:00H01JUN2021 1.900
00:10H01JUN2021 2.400
00:20H01JUN2021 2.100
00:30H01JUN2021 2.300
00:40H01JUN2021 2.00
00:50H01JUN2021 2.300
01:00H01JUN2021 2.300
01:10H01JUN2021 0.000
01:20H01JUN2021 2.200
01:30H01JUN2021 0.100

数据说明:

  • 第一列为日期时间,格式为HH:MMHDDMMMYYYY,其中前6个字符YY:XXH里,YY是小时,XX是分钟
  • 第二列为对应时间的数值

期望转换为带标准数字日期格式的CSV文件ofile.txt,内容如下:

yyyy-mm-dd hh:mm:ss,val
2021-06-01 00:00:00,1.900
2021-06-01 00:10:00,2.400
2021-06-01 00:20:00,2.100
2021-06-01 00:30:00,2.300
2021-06-01 00:40:00,2.000
2021-06-01 00:50:00,2.300
2021-06-01 01:00:00,2.300
2021-06-01 01:10:00,0.000
2021-06-01 01:20:00,2.200
2021-06-01 01:30:00,0.100

我编写的脚本无法得到预期结果:

#!/bin/sh
gawk '
    BEGIN {
        month["Jan"] = "01"; month["Feb"] = "02"; month["Mar"] = "03";
        month["Apr"] = "04"; month["May"] = "05"; month["Jun"] = "06";
        month["Jul"] = "07"; month["Aug"] = "08"; month["Sep"] = "09";
        month["Oct"] = "10"; month["Nov"] = "11"; month["Dec"] = "12";
    }
    function timestamp_to_numeric(s) {
        # 00:00H01JUN2021 => 2021-06-01 00:00:00
        return substr(s,12,4)"-"month[substr(s,9,3)]"-"substr(s,7,2) substr(s,1,2)":"substr(s,4,2)":""00"
    }
    NR==1 {next}
    END {
            printf "%s",timestamp_to_numeric($1),$2
            printf "\n"
        }
   ' ifile.txt

解决方案

原脚本问题分析

  1. 错误跳过第一行数据:NR==1 {next}会跳过输入的第一行有效数据,但输入文件没有表头,所有行都是数据行。
  2. 仅处理最后一行:所有处理逻辑放在END块中,只会在所有行读完后执行一次,仅输出最后一行的结果。
  3. 时间格式拼接错误:timestamp_to_numeric函数中,日期部分和时间部分之间缺少空格,会生成类似2021-06-0100:00:00的错误格式。
  4. 月份匹配失败:输入中的月份是大写(如JUN),但脚本中用的是小写(Jun),导致无法正确映射月份数字。
  5. 数值格式不统一:输入中存在2.00这种两位小数的数值,需要统一格式化为三位小数。

修正后的脚本

#!/bin/sh
gawk '
    BEGIN {
        # 输出CSV表头
        print "yyyy-mm-dd hh:mm:ss,val"
        # 月份映射,使用大写匹配输入格式
        month["JAN"] = "01"; month["FEB"] = "02"; month["MAR"] = "03";
        month["APR"] = "04"; month["MAY"] = "05"; month["JUN"] = "06";
        month["JUL"] = "07"; month["AUG"] = "08"; month["SEP"] = "09";
        month["OCT"] = "10"; month["NOV"] = "11"; month["DEC"] = "12";
    }
    function timestamp_to_numeric(s) {
        # 拆分时间和日期各分量
        hour = substr(s, 1, 2)
        minute = substr(s, 4, 2)
        day = substr(s, 7, 2)
        mon = substr(s, 9, 3)
        year = substr(s, 12, 4)
        # 拼接为标准格式,添加日期与时间的分隔空格
        return year "-" month[mon] "-" day " " hour ":" minute ":00"
    }
    # 逐行处理数据
    {
        # 格式化数值为三位小数,确保格式统一
        printf "%s,%.3f\n", timestamp_to_numeric($1), $2
    }
' ifile.txt > ofile.txt

修正点说明

  1. 添加表头输出:在BEGIN块中先打印CSV的表头行,符合预期输出格式。
  2. 修正月份映射键:将月份缩写改为大写,匹配输入中的JUN格式,确保月份数字正确映射。
  3. 重构时间转换函数:拆分各时间分量后再拼接,明确添加日期和时间之间的空格,避免格式错误。
  4. 遍历处理每一行:将处理逻辑放在主循环中,逐行转换并输出所有数据。
  5. 统一数值格式:使用%.3f格式化数值,自动将两位小数补为三位(如2.00转为2.000)。

验证结果

执行修正后的脚本,输出文件ofile.txt将完全符合预期的CSV格式要求。


内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:15:31