【问题标题】:Passing awk variable to strftime将 awk 变量传递给 strftime
【发布时间】:2016-03-17 21:40:32
【问题描述】:

我有一个 CSV,其中第 2 列和第 3 列分别是日期和时间(以 UTC 为单位)。

Id,Date,Hour,Name,...
1,2016-02-01,13:52,name1,...
2,2016-02-01,11:02,name2,...
3,2016-01-30,17:43,name3,...
4,2016-01-29,20:07,name4,...
5,2016-01-29,20:05,name5,...
.
.
.

我需要将其转换并合并到德国时间(广义,CET/CEST)。我首先将第 2 列和第 3 列连接到一个 awk 变量中作为a,但我无法将它作为第二个参数传递给函数strftime:

TZ="Europe/Berlin" awk 'BEGIN { FS=OFS=","} NR!=1 {a=$2" "$3" UTC"} {print strftime("%F %H.%M.%S %Z", a)}' <csv-file>

如何在 strftime 函数中传递 awk 变量 a?

【问题讨论】:

  • 通过将a 放在与您尝试使用它的位置相同的范围内?

标签: bash csv awk gawk


【解决方案1】:

首先,awk 是一个强大的文本处理工具,但是对于日期和时间,它就不是那么好。

如果你想使用它的 strftime(),你必须提供一个 awk 接受的 timestamp,例如来自 awk 的 systime() or mktime()。但是,如果您想进行时区转换,则不能使用mktime()。因为它将在您的本地时区加载datespec。

更简单的方法是,使用外部 gnu date 命令,您可以对日期进行相当多的控制。

我假设用 awk 处理列对你来说没有问题,我只是用日期部分做一个例子:

假设你以某种方式创建了一个字符串:"2016-02-01 13:52 UTC"

echo "2016-02-01 13:52 UTC"|awk -v q='"' 
       '{cmd="TZ=Europe/Berlin date -d"q$0 q" +"q"%F %H.%M.%S %Z"q;
        cmd|getline x;
        close(cmd);print x}'

这将给出:

2016-02-01 14.52.00 CET

所以时区被转换了。请注意,getline 管道后的close(cmd) 很重要。

【讨论】:

  • 如果/当cmd | getline 失败时(可能没有警告)输出x 的先前值。你需要像if ( (cmd | getline x) &lt;= 0 ) x="N/A" 这样的东西。见awk.info/?tip/getline。
  • 请注意,date 的 -d 选项特别适用于 GNU 版本(coreutils)。 BSD、Solaris 等中的date 命令功能不同。这似乎是对与操作系统无关的问题的以 Linux 为中心的答案。
【解决方案2】:

awk 日期处理并不像您想象的那么灵活。您不能将任意格式的时间戳传递给 strftime。我会恢复到系统日期 这是一个示例脚本:

$ echo 1,2016-02-01,13:52,name1,... | 
  awk -F, '{cmd = "date -d \"" $2 " " $3 "\" \"+%F %H.%M.%S %Z\""; cmd | getline d; print d}'

2016-02-01 13.52.00 EST

【讨论】:

  • 等等,这个结果正确吗? 13:52 UTC 应该是德国时间 14:52 对吧?它不进行转换,是吗?
  • 你能解释一下变量 $2 和 $3 周围的双引号吗?
  • 它们实际上在双引号之外,它连接了字符串和变量中的日期命令字符串。像这样“xxx”++ $2 ++“”++ $3 ++“xxx”。但是,我没有合并 TZ,这可能是您的问题。
猜你喜欢
  • 2018-09-28
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多