使用日期转换列并附加到 csv 文件

使用日期转换列并附加到 csv 文件

我有一个 CSV,其中第一列有一个表示日期时间的字符串。我想添加一个额外的列,并将日期时间转换为纪元。
我尝试了以下方法:

awk -F "," 'BEGIN{ OFS="," } {$14=$(date -jf "%m/%d/%Y %H:%M:%S %p" $1 "+%s"); print}’ mycsv.csv > test  

我得到:

awk: illegal field $(0%m/%d/%Y %H:%M:%S %p"1/30/2017 11:14:55 AM"+%s), name "(null)"
 input record number 1, file mycsv.csv
 source line number 1  

我知道该字段的日期转换有效,所以我在语法上做了一些错误。
我怎样才能做我想做的事?

答案1

我有 GNU date,因此命令行选项对我来说是不同的。但你的问题似乎是 awk 的语法:你不能$(...)在 awk 脚本中使用 shell 子进程构造。您需要一个system()函数,该函数传递一个字符串。因此,您需要将有效的 shell 命令构造为 awk 字符串,您可以将其传递到 awk 脚本内的系统。

像这样的东西:

awk -F "," 'BEGIN{ OFS="," } {$14=system("date -jf \"%m/%d/%Y %H:%M:%S %p\" \""$1"\" \"+%s\""); print}' mycsv.csv > test

或者为了更好的可读性

awk -F "," '
  BEGIN{ OFS="," }
  {
    $14 = system("date -jf \"%m/%d/%Y %H:%M:%S %p\" \"" $1 "\" \"+%s\"");
    print
  }' \
  mycsv.csv > test

答案2

如果你有 GNU awk(我认为应该可以在 OSX 上使用brew),那么你可以使用内部的mktimestrftime不是依赖于 system date

不幸的是你的输入格式不在日期规范所期望的格式mktime,因此需要对时间字符串进行一些分割和重新排列。例如,给定

$ cat file.csv 
09/23/2016 11:12:19 AM,field2,field3

然后

gawk -F, '
  {
    split($1,a,/[/: ]/);
    ts = sprintf("%4d %02d %02d %2d %2d %2d", a[3], a[2], a[1], a[7] ~ /^[Pp]/ ? a[4]+12 : a[4], a[5], a[6]); 
    $0 = strftime("%s", mktime(ts)) FS $0
  } 1' file.csv
1510243939,09/23/2016 11:12:19 AM,field2,field3

答案3

使用 Miller(mlr,在 macOS 上通过 Homebrew 作为软件包提供miller),并假设您的输入是无标头 CSV 文件,并且您希望通过解析字段 1 中的格式化日期将 Unix 时间戳写入字段 14:

mlr --csv -N put '$14 = strptime($1,"%m/%d/%Y %H:%M:%S %p")' mycsv.csv

如果您有标题,则删除该-N选项并使用命名字段而不是数字字段,例如$timestamp = strptime($date, ...).

strptime()函数使用提供的模式解析格式化日期并返回 Unix 时间戳。

对于问题中提到的日期,假设它位于 UTC 时区,新字段将获得值1485774895.000000。您是否想考虑当地时区,请使用strptime_local()代替strptime().如果您只需要 Unix 时间戳的整数部分,请将调用包装strptime()int(...).

相关内容