就地在文件中将时间戳转换为纪元

Convert timestamp to epoch in a file in-place

我有一个 tab 分隔文件,在第三个字段中带有时间戳,我需要将其更改为 bash 中的纪元。

示例输入:

xyz@gmail.com   SALE    2017-04-26 12:47:27     30.0    1       201704
xyz@gmail.com   SALE    2017-04-26 12:46:15     20.0    2       201704
xyz@gmail.com   PAYBACK 2017-04-18 08:02:31     95.0    3       201704
xyz@gmail.com   SEND    2017-04-18 08:00:37     4800.0  4       201704
xyz@gmail.com   SEND    2017-04-17 14:59:34     4900.0  5       201704

我尝试了 awk 'BEGIN {IFS="\t"} {=system("date -d \"""\" '+%s'");print}' file,它给出了最接近的结果,但它在一行中显示纪元,然后在时间戳值为零的换行符中再次显示记录。我需要在一条记录中全部替换第三个字段。

使用 GNU awk:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
     = mktime(gensub(/[-:]/," ","g",))
    print
}

$ awk -f tst.awk file
xyz@gmail.com   SALE    1493228847      30.0    1       201704
xyz@gmail.com   SALE    1493228775      20.0    2       201704
xyz@gmail.com   PAYBACK 1492520551      95.0    3       201704
xyz@gmail.com   SEND    1492520437      4800.0  4       201704
xyz@gmail.com   SEND    1492459174      4900.0  5       201704

与其他 awks:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    cmd = "date -d \""  "\" 7+%s7"
    if ( (cmd | getline line) > 0 ) {
         = line
    }
    close(cmd)
    print
}

$ awk -f tst.awk file
xyz@gmail.com   SALE    1493228847      30.0    1       201704
xyz@gmail.com   SALE    1493228775      20.0    2       201704
xyz@gmail.com   PAYBACK 1492520551      95.0    3       201704
xyz@gmail.com   SEND    1492520437      4800.0  4       201704
xyz@gmail.com   SEND    1492459174      4900.0  5       201704

wrt 你的脚本 - 没有名为 IFS 的内置 awk 变量,system returns 最后一个命令的退出状态 运行,不是标准输出,并且您不能在从 shell.

调用的任何 ' 分隔的脚本中包含 's

wrt 想要这样做 "in-place",没有 UNIX 编辑器真正进行就地编辑,但在 GNU awk 中,您可以使用 -i inplace 来避免自己指定 tmp 文件名。但是,对于任何 UNIX 命令,您只需执行 cmd file > tmp && mv tmp file.

请注意,这是 getline 为数不多的适当用途之一 - 请参阅 http://awk.freeshell.org/AllAboutGetline 了解其他有效用途,最重要的是,除非绝对必要,否则请注意不要使用它的警告和原因。