【问题标题】:AWK: convert timestamp to epoch; first record always returns -1AWK:将时间戳转换为纪元;第一条记录总是返回 -1
【发布时间】:2021-06-27 22:37:32
【问题描述】:

我有一个带有时间戳和里程表读数的输入文件,如下所示:

2017-09-16 18:14:00,80465
2017-09-19 18:23:00,80898
2017-09-21 08:05:00,81253
2017-09-27 18:20:00,82155
2017-10-03 18:36:00,82902
2017-10-09 18:33:00,83699

...并想添加转换为纪元的时间戳,代码如下:

BEGIN {}
{
    # change timestamp to epoch (without TZ correction)
    epoch_returned = timestamp_to_epoch($1)
    printf("%s,%s\n", $0, epoch_returned)
}

function timestamp_to_epoch(timestamp_in) {
    FPAT = "[0-9][0-9]"
    epoch_out = mktime($1$2" "$3" "$4" "$5" "$6" "$7)
    return epoch_out
}

输出产生这个:

2017-09-16 18:14:00,80465,-1
2017-09-19 18:23:00,80898,1505809380
2017-09-21 08:05:00,81253,1505945100
2017-09-27 18:20:00,82155,1506500400
2017-10-03 18:36:00,82902,1507019760
2017-10-09 18:33:00,83699,1507537980

第一行总是返回 -1。 我已经删除了输入文件中的第一行,(然后)第一行仍然返回-1。 我在输入中只留下了一行。也返回 -1。

如果我在输入文件中输入一个空行,它将返回 -1,而所有其他都按预期添加纪元。

这个我看了好久还是想不通。

我在Linux Mint 20.1 Cinnamon 4.8.6上使用GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)

任何提示表示赞赏。

【问题讨论】:

    标签: awk timestamp epoch


    【解决方案1】:

    将 FPAT 行移到 BEGIN 块中。当您第一次调用该函数时,awk 已经使用默认的 FS 将行拆分为字段。

    而且您直接在函数中使用编号字段,因此传递参数没有意义。

    【讨论】:

    • 我以前从未使用过 FPAT;你的第二句话刚刚点击了我,现在了解构造/工作原理。
    【解决方案2】:

    如果您想使用 FPAT 将输入拆分为字段,那么您将在错误的位置使用它,它必须位于 BEGIN 部​​分,但这不是您想要做的,您的数据是 ,-separated 并且您只是想将您的时间戳分成 2 位数字段。为此,您可以使用 patsplit() 而不是 FPAT(两者都是 gawk-only,就像 mktime()):

    $ cat tst.awk
    BEGIN { FS=OFS="," }
    {
        # change timestamp to epoch (without TZ correction)
        epoch_returned = timestamp_to_epoch($1)
        print $0, epoch_returned
    }
    
    function timestamp_to_epoch(timestamp_in,       t, epoch_out) {
        patsplit(timestamp_in,t,/[0-9][0-9]/)
        epoch_out = mktime(t[1] t[2] " " t[3] " " t[4] " " t[5] " " t[6] " " t[7])
        return epoch_out
    }
    

    $ awk -f tst.awk file
    2017-09-16 18:14:00,80465,1505603640
    2017-09-19 18:23:00,80898,1505863380
    2017-09-21 08:05:00,81253,1505999100
    2017-09-27 18:20:00,82155,1506554400
    2017-10-03 18:36:00,82902,1507073760
    2017-10-09 18:33:00,83699,1507591980
    

    但我个人会使用普通的旧split() 而不是patsplit()

    split(timestamp_in,t,/[- :]/)
    epoch_out = mktime(t[1] " " t[2] " " t[3] " " t[4] " " t[5] " " t[6])
    

    【讨论】:

    • 我最终采用了 split() 方法。
    猜你喜欢
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2021-01-18
    • 2013-03-25
    • 2018-08-03
    • 1970-01-01
    • 2020-06-24
    相关资源
    最近更新 更多