Bash 将YYYY-MM-DD HH:MM:SS转换为相对于0的秒数
有一个csv文件,其中行有5个用逗号分隔的字段:Bash 将YYYY-MM-DD HH:MM:SS转换为相对于0的秒数,bash,shell,csv,time,text-processing,Bash,Shell,Csv,Time,Text Processing,有一个csv文件,其中行有5个用逗号分隔的字段: 2020-07-31 15:15:55,xx,yy,zz,t 2020-07-31 15:16:57,xx,yy,zz,t 2020-07-31 15:17:00,xx,yy,zz,t 我想使用第一行作为0,单位为秒(相对时间),因此输出如下: 0,xx,yy,zz,t 62,xx,yy,zz,t 65,xx,yy,zz,t cat file.csv | awk -F, '{ OFS = FS;command="date -d &q
2020-07-31 15:15:55,xx,yy,zz,t
2020-07-31 15:16:57,xx,yy,zz,t
2020-07-31 15:17:00,xx,yy,zz,t
我想使用第一行作为0,单位为秒(相对时间),因此输出如下:
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" $1 "\"" " +%s";command | getline $1;close(command);print}'
1596201355,xx,yy,zz,t
1596201417,xx,yy,zz,t
1596201420,xx,yy,zz,t
我可以使用任何编程语言,如bash、awk、sed、perl。。。并覆盖相同的文件或创建一个新文件。perl-MTime::Piece-F,-lane'
开始{$,=“,”}
$t=Time::Piece->strtime(shift(@F),%F%t”)->epoch;
如果($。==1){$start=$t}
打印$t-$start,@F;
"档案"
这是一个部分答案,考虑到白天不会改变,所以省略了它
cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,' '{printf ($1*3600+$2*60+$3)}{print ","$4","$5","$6","$7}'
这将输出该结果,该结果仍保留第一个值,该值可以从文件中读取:
54955,xx,yy,zz,t
55017,xx,yy,zz,t
55020,xx,yy,zz,t
现在,由于所有行的值都相同,因此可以手动输入:
cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,' '{printf ($1*3600+$2*60+$3-54955)}{print ","$4","$5","$6","$7}'
这将产生预期的结果:
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
***
后来添加:多亏了这个线程,才有了将时间转换为历元的方法,这是绝对的:
所以它仍然是这样的:
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" $1 "\"" " +%s";command | getline $1;close(command);print}'
1596201355,xx,yy,zz,t
1596201417,xx,yy,zz,t
1596201420,xx,yy,zz,t
**
稍后再次添加:
静止第一个值的方法是使用以下awk表达式:
| awk -F, 'NR==1{pattern=$1}{printf ($1-pattern)}{print ","$2","$3","$4","$5}'
因此,前面介绍的两种方法将保持如下:
只有在同一天,这个案例才会起作用:
cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,' '{printf ($1*3600+$2*60+$3)}{print ","$4","$5","$6","$7}' | awk -F, 'NR==1{pattern=$1}{printf ($1-pattern)}{print ","$2","$3","$4","$5}'
这(使用历元)将考虑以下天数:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" $1 "\"" " +%s";command | getline $1;close(command);print}' | awk -F, 'NR==1{pattern=$1}{printf ($1-pattern)}{print ","$2","$3","$4","$5}'
迄今为止的最佳解决方案:将考虑使用epoch的天数,并将使用任何awk变体,包括BSD变体。此外,它还检测有多少字段,即使只有第一个字段也可以工作:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" $1 "\"" " +%s";command | getline $1;close(command);print}' | awk -F, 'NR==1{pattern=$1}{printf ($1-pattern)}{if (NF > 1){for (i = 2; i < NF; i += 1) printf ","$i; print ","$NF} else print ""}'
结果:
0,xx
62,xx
65,xx
这是UNIX环境无法轻松处理的问题。 利用
$teip-d,-f1--sh-c“date-f-+%s”
由@anubhava提供的原始答案(只有两个字段):
您可以将此awk
与mktime
功能一起使用。
这将输出由逗号分隔的两个字段:
awk 'BEGIN {
FS=OFS="," # set input and output field separators to comma
}
{
gsub(/[-:]/, " ", $1) # replace - and : with a space
tm = mktime($1) # convert date-time string to EPOCH value
if (NR == 1) # for 1st records store this value in first
first = tm
print (tm - first), $2 # print difference and 2nd field for each record
}' file
结果:
0,xx
62,xx
65,xx
由@smeterlink改进 这将使用NF变量检测所有以逗号分隔的字段,因此即使只有第一个字段也可以工作。这样,可以混合不同数量字段的行: get.awk: 结果:
0,xx
62,xx
65,xx
你试过什么吗?如果你想要一个指针,我会先搜索“awk日期操纵”StackOverflow不是一个“我们会免费为你做你的工作”的网站。展示你的努力,而不是要求一个现成的解决方案。显示您需要帮助的具体错误和您期望的示例输出。@Smeterlink,您能告诉我们获得期望输出的逻辑吗,对不起,我不清楚。请显示您的尝试,以便我们知道您的困境。您应该阅读以确认您的回答者的努力。您需要打印到
$5
,这里有一行代码:awk'BEGIN{FS=OFS=“,”}{gsub(/[-:]/,”,”,$1);tm=mktime($1);if(NR==1)first=tm;print(tm-first),$2,$3,$4,$5}file.csv
谢谢您的编辑。我的答案是基于您原来的问题,您除了时间戳之外只有一个值。扩展了帖子并保留了您原来的答案,同时添加了一个新答案,该答案将动态调整为可变的字段数。mktime
与原始awk
2020-07-31 15:15:55,xx,yy,zz,t
2020-07-31 15:16:57,xx,yy,zz,t
2020-07-31 15:17:00,xx,yy,zz,t
2020-07-31 15:17:23,xx,yy,zz,abc,009-%5
2020-07-31 15:18:00
2020-07-31 15:19:00,xx
awk -f get.awk file.csv
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
88,xx,yy,zz,abc,009-%5
125
185,xx