使用 AWK 将日期转换为多列上的纪元值

使用 AWK 将日期转换为多列上的纪元值
A,B,C,D
1,30/07/2014,data_n/a,data_n/a
2,30/07/2014,22/02/2018,data_n/a
3,26/02/2015,22/12/2016,28/07/2017

我想一次性将所有日期转换为纪元格式。我尝试让以下代码运行,但它只输出 2 列。

gawk -F, '{for (i=1; i<=4; i++) split($i,date,"/");
           $i=mktime(date[3] " " date[2] " " date[1] " " "00 00 00"); 
           printf $i","; if (NF >=1 ) print $1; }'

我究竟做错了什么?

答案1

我究竟做错了什么?

您正在构建for这样的循环:

for (i=1; i<=4; i++) split($i,date,"/")

我的意思是全部的循环。后面的代码不属于循环。循环结束后, 的最后一个值i仍然存在,并且date来自最后一个split

最有可能的是,您希望在 之前(或之后)结束循环if (NF >=1 ) print $1。因为您似乎对 的处理$1方式不同或许您想从哪里开始i=2。由于不清楚输出应该是什么,我不确定您真正想要的确切程序。可能是这样的:

gawk -F, '{for (i=2; i<=4; i++) {split($i,date,"/");
           $i=mktime(date[3] " " date[2] " " date[1] " " "00 00 00"); 
           printf $i","} if (NF >=1 ) print $1; }'

无论如何,我认为这里最大的问题是

for ( … ) single_command

你需要

for ( … ) { multiple; commands }

答案2

在编写程序时格式化可能会有所帮助 - 这样您可能会看到哪里出了问题:

{
    for (i=1; i<=4; i++)
        split($i,date,"/");
    $i=mktime(date[3] " " date[2] " " date[1] " " "00 00 00");
    printf $i",";
    if (NF >=1 )
        print $1;
}
  • 现在应该清楚的是,$i=mktime()andprintf语句在for循环之外

以下是使用 GNU 的另一种方法awk

$ cat script.awk
BEGIN { FS=OFS="," }
FNR > 1 {
    for (i=2; i <= NF; i++)
        if ($i ~ /^([[:digit:]]+\/){2}[[:digit:]]{4}$/) {
            split($i, date, "/")
            $i = mktime(date[3]" "date[2]" "date[1]" 0 0 0")
        }
}
1
$ awk -f script.awk file
A,B,C,D
1,1406642400,data_n/a,data_n/a
2,1406642400,1519221600,data_n/a
3,1424872800,1482328800,1501164000

  • 用作,输入和输出字段分隔符
  • 在线数字1大于文件
    • 循环i2NF
    • 如果该字段$i看起来像日期:
      • 拆分成组件
      • 将结果指定mktime()为该字段的新值
  • 打印每一行

如果输入文件中的日期是 UTC,则添加utc 标志mktime()

mktime(date[3]" "date[2]" "date[1]" 0 0 0", 1)

相关内容