![使用日期转换列并附加到 csv 文件](https://linux22.com/image/104504/%E4%BD%BF%E7%94%A8%E6%97%A5%E6%9C%9F%E8%BD%AC%E6%8D%A2%E5%88%97%E5%B9%B6%E9%99%84%E5%8A%A0%E5%88%B0%20csv%20%E6%96%87%E4%BB%B6.png)
我有一个 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
),那么你可以使用内部的mktime
而strftime
不是依赖于 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(...)
.