带有 GAWK 的 CSV 文件中的 Epoch 时间戳

Posted

技术标签:

【中文标题】带有 GAWK 的 CSV 文件中的 Epoch 时间戳【英文标题】:Timestamp to Epoch in a CSV file with GAWK 【发布时间】:2013-12-16 20:35:15 【问题描述】:

希望使用 GAWK 将人类可读的时间戳转换为 CSV 文件中的纪元/Unix 时间,以准备加载到 mysql 数据库中。

数据示例:

null;2013-11-26;Text & Device;Location;/file/path/to/;Tuesday, November 26 12:17 PM;1;1385845647

希望在 11 月 26 日星期二下午 12:17 获取第 6 列,并将其转换为纪元时间进行存储。显示的所有时间都将采用 EST 格式。我意识到 AWK 是用于此目的的工具,但似乎不能完全构建命令。目前有:

cat FILE_IN.CSV | awk 'BEGIN FS=OFS=";"$6=strftime("%s") print' 

但是这会返回:

null;2013-11-26;Text & Device;Location;/file/path/to/;1385848848;1;1385845647

大概,这意味着我正在调用当前纪元时间(1385848848 是执行时的当前纪元),而不是要求strftime 转换字符串;但我无法想象另一种方式来做到这一点。

gawk/strftime 将现有时间戳转换为纪元的正确语法是什么?

编辑:这个问题似乎与How do I use output from awk in another command? 关系不大

【问题讨论】:

strftime 用于格式化已经采用纪元时间戳形式的时间;它不解析其他格式。为此,您可以使用strptime,但 Gawk 不提供。可能是时候接触 Perl 了。 不幸的是,卡在了限制我只能使用 BASH 的公司系统中。 困惑。如果您可以拨打gawk,您可以拨打perl... 我可以调用 perl,但 sysadmin 要求所有脚本只能在 bash 中完成。我意识到这很愚蠢,但没有立场争论。 perl -ae 'code goes here'awk 'code goes here' 一样是一个 bash 脚本。 【参考方案1】:
$ cat file
null;2013-11-26;Text & Device;Location;/file/path/to/;Tuesday, November 26 12:17 PM;1;1385845647

$ gawk 'BEGINFS=OFS=";" gsub(/-/," ",$2); $2=mktime($2" 0 0 0")1' file
null;1385445600;Text & Device;Location;/file/path/to/;Tuesday, November 26 12:17 PM;1;1385845647

以下是如何将日期从任何格式转换为自纪元以来的秒数,以您当前的格式为例,并使用 cmets 逐步显示转换过程:

$ cat tst.awk
function cvttime(t,     a) 
    split(t,a,/[,: ]+/)
    # 2013 Tuesday, November 26 10:17 PM
    #  =>
    #    a[1] = "2013"
    #    a[2] = "Tuesday"
    #    a[3] = "November"
    #    a[4] = "26"
    #    a[5] = "10"
    #    a[6] = "17"
    #    a[7] = "PM"

    if ( (a[7] == "PM") && (a[5] < 12) ) 
        a[5] += 12
    
    # => a[5] = "22"

    a[3] = substr(a[3],1,3)
    # => a[3] = "Nov"

    match("JanFebMarAprMayJunJulAugSepOctNovDec",a[3])
    a[3] = (RSTART+2)/3
    # => a[3] = 11

    return( mktime(a[1]" "a[3]" "a[4]" "a[5]" "a[6]" 0") )


BEGIN 
    mdt ="Tuesday, November 26 10:17 PM"
    secs = cvttime(2013" "mdt)
    dt = strftime("%Y-%m-%d %H:%M:%S",secs)
    print mdt ORS "\t-> " secs ORS "\t\t-> " dt

$ awk -f tst.awk
Tuesday, November 26 10:17 PM
        -> 1385525820
                -> 2013-11-26 22:17:00

我相信您可以针对当前问题进行修改。

另外,如果你没有 gawk,你可以将 cvttime() 函数写成(借用@sputnik 的date 命令字符串):

$ cat tst2.awk
function cvttime(t,     cmd,secs) 
    cmd = "date -d \"" t "\" '+%s'"
    cmd | getline secs
    close(cmd)
    return secs


BEGIN 
    mdt ="Tuesday, November 26 10:17 PM"
    secs = cvttime(mdt)
    dt = strftime("%Y-%m-%d %H:%M:%S",secs)
    print mdt ORS "\t-> " secs ORS "\t\t-> " dt

$
$ awk -f tst2.awk
Tuesday, November 26 10:17 PM
        -> 1385525820
                -> 2013-11-26 22:17:00

我把 srtftime() 留在那里只是为了表明秒数是正确的 - 用你认为合适的 date 替换。

对于非 gawk 版本,您只需要弄清楚如何以 date 理解的方式将年份输入到输入的月份/日期/时间字符串中 - 应该不难。

【讨论】:

这只是回答了问题,但希望转换列 $6 而不是 $2。区别在于格式; “11 月 26 日,星期二,下午 12:17”。非常有助于让我到达那里,一直在玩各种选择。 啊,我没注意到。由于该字段没有年份 - 我们可以使用 2 美元起的日期和 6 美元起的时间,或者我们应该如何确定年份? 我已经更新了我的答案,以展示如何从任何日期格式转换为自纪元以来的秒数 - 您可以调整以提供您认为合适的年份。 是的,假设 2 美元的年份是一样的,非常感谢您的帮助! 不客气,感谢您接受答案,我刚刚添加了 cvttime() 函数的非 gawk 版本,以防您发现系统管理员认为 gawk 不可接受毕竟。【参考方案2】:

您可以使用这个 sn-p 将日期转换为纪元:

$ date -d 'Tuesday, November 26 12:17 PM' +%s
1385464620

最后:

awk -F";" 'system("date -d \""$6"\" '+%s'")' file

感谢@Keiron 的 sn-p。

【讨论】:

早些时候正是这样尝试,但想不出一种方法来为 CSV 的每一行调用命令。有没有办法嵌入类似的东西: date -d $6 '+%s' 这是我在该方法中使用的代码:cat FILE_IN.csv | awk -F";" 'system("date -d "$6" '+%s'")' 发现语法错误awk -F";" 'system("date -d \""$6"\" '+%s'")'

以上是关于带有 GAWK 的 CSV 文件中的 Epoch 时间戳的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有 YYYYMMDD 列的 CSV 文件导入 ClickHouse 中的 DATE 列

如何在多个文件中搜索字符串并在 Excel 或 Powershell 中的 csv 中返回带有行号/文本的文件名

我可以从带有标题的 csv 文件在 PostgreSQL 中自动创建一个表吗?

将固定宽度的文件从文本转换为 csv

带有熊猫迭代器对象的 Keras fit_generator

将csv文件格式的数据传到SQL2008数据库中后,表中的每一列都带有双引号,这个双引号怎样才能去掉?