文件我有一个CSV带时间戳和一些数据值文件:在CSV更换色谱柱用一分钟的间隔时间戳记
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
...etc
但我想更换新的时间戳值的时间戳列。最后一行应该是当前时间,并且所有先前的行应比它之后的行早一分钟。
如何使用shell脚本执行此操作庆典/ AWK?
文件我有一个CSV带时间戳和一些数据值文件:在CSV更换色谱柱用一分钟的间隔时间戳记
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
...etc
但我想更换新的时间戳值的时间戳列。最后一行应该是当前时间,并且所有先前的行应比它之后的行早一分钟。
如何使用shell脚本执行此操作庆典/ AWK?
则可以反向使用tac
文件内容,做了手术,然后反向回原来的顺序:
tac file.txt | \
awk 'BEGIN{FS=OFS=","} NR==1{"date +%s"|getline cur; $1=cur; print; next}; \
{$1=cur-(60*(NR-1)); print}' | tac
对于(反转)第一行,我们得到当前时间戳的时代,并将其保存在一个变量cur
对于下一行,我们通过60 * (line number - 1)
秒减去每行获得所需的时间
请注意,时间计算可能并不像您想象的那样精确。
例子:
% cat ts.txt
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
% tac ts.txt | awk 'BEGIN{FS=OFS=","} NR==1{"date +%s"|getline cur; $1=cur; print; next}; {$1=cur-(60*(NR-1)); print}' | tac
1475497096,76.357,899.500,326.717,8.000
1475497156,76.490,899.650,326.150,8.000
1475497216,76.357,899.500,326.717,8.000
1475497276,76.490,899.650,326.150,8.000
根据我对Aaron的回答的评论,在Q中没有迹象表明OP正在运行可能包含'tac'的操作系统,所以我提到了一些替代方案。 – ghoti
这里是我会怎么做:
tac inputFile | awk -v ts="$(date +%s)" -v OFS=, -F, '{ $4 = strftime("%c", ts - NR * 60) ; print $0 }' | tac
tac
反向输入文件,这样我们就可以从已知的唯一值计算的日期,目前日期。我们将在处理完每一行后恢复它。
awk
的-v
标志为我们提供了使用一个变量的能力,所以我们让bash
计算当前时间戳,并将它传递给awk
作为UNIX时间戳(秒数自01/01/1970)。
awk
的-F
标志指定列分隔符。
然后在每一行中,最后一列由给定的时间戳替换,每个先前读取的行减去60秒,我们使用strftime以人类可读的格式显示。
实施例:
$ cat inputFile
a,b,c,d
a1,b1,c1,d1
a2,b2,c2,d2
$ tac inputFile | awk -v ts="$(date +%s)" -v OFS=, -F, '{ $4 = strftime("%c", ts - NR * 60) ; print $0 }' | tac
a,b,c,lun. 3 oct. 2016 15:32:29
a1,b1,c1,lun. 3 oct. 2016 15:33:29
a2,b2,c2,lun. 3 oct. 2016 15:34:29
如果您使用的操作系统不包含'tac'(如FreeBSD或OS X或Solaris或AIX等),请检查您的'tail'命令是否有'-r'选项。如果失败了,你可以用'awk'{L [i ++] = $ 0}得到类似的结果(假设你有内存来保存文件)END {for(j = i-1; j> = 0;)print L [J - ]}“'。 – ghoti
这羚awk脚本首先获取当前时间戳(信号出现时间),在第一次迭代记录着文件的NR
并在第二次迭代更新的时间戳之后:
$ awk -F, 'BEGIN{ts=strftime("%s")} NR==FNR{nr=NR; next}{$1=ts-(nr-FNR)*60} 1' file file
1455840000 76.357 899.500 326.717 8.000
1455840060 76.490 899.650 326.150 8.000
For compatibility with all awks — including Gnu awk — replace BEGIN{}
block above with
BEGIN{"date +'%s'"|getline ts}
'strftime()'函数是GNU awk的一部分,但不是我知道的其他变体。 – ghoti
这可能是你想要什么:
$ cat file
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
1455840000,76.357,899.500,326.717,8.000
1455840060,76.490,899.650,326.150,8.000
随着GNU AWK:
$ awk 'BEGIN{FS=OFS=","; now=systime()} NR>FNR{$1 = now - (NR-2*FNR)*60; print}' file file
1475504973,76.357,899.500,326.717,8.000
1475505033,76.490,899.650,326.150,8.000
1475505093,76.357,899.500,326.717,8.000
1475505153,76.490,899.650,326.150,8.000
1475505213,76.357,899.500,326.717,8.000
1475505273,76.490,899.650,326.150,8.000
与其他awks:
$ awk -v now=$(date +'%s') 'BEGIN{FS=OFS=","} NR>FNR{$1 = now - (NR-2*FNR)*60; print}' file file
1475504973,76.357,899.500,326.717,8.000
1475505033,76.490,899.650,326.150,8.000
1475505093,76.357,899.500,326.717,8.000
1475505153,76.490,899.650,326.150,8.000
1475505213,76.357,899.500,326.717,8.000
1475505273,76.490,899.650,326.150,8.000
我们如何知道'start'和'结束'时间戳?我们从哪里开始和结束? – Inian
@Inian结束时间戳是当前时间。然后以相反的顺序在一分钟内递减到文件的开始递减。该文件可以是任何长度,因此除了计算行数之外,我们不知道开始时间戳。 – mtmacdonald
当你说_然后以相反的顺序迭代到file_的开始时,什么定义_start_? – Inian