就地在文件中将时间戳转换为纪元
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 了解其他有效用途,最重要的是,除非绝对必要,否则请注意不要使用它的警告和原因。
我有一个 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 了解其他有效用途,最重要的是,除非绝对必要,否则请注意不要使用它的警告和原因。