将 YYYY-MM-DD HH:MM:SS 转换为相对于 0 的秒数
Convert YYYY-MM-DD HH:MM:SS to seconds relative to 0
有一个 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
我可以使用任何编程语言来完成,例如 bash、awk、sed、perl...并覆盖相同的文件或创建一个新文件。
perl -MTime::Piece -F, -lane '
BEGIN {$, = ","}
$t = Time::Piece->strptime(shift(@F), "%F %T")->epoch;
if ($. == 1) {$start = $t}
print $t - $start, @F;
' file
这是一个有效的部分答案,考虑到日期不会改变,因此被省略。
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+)}{print ","","","","}'
这将输出这个结果,它仍然没有休息第一个值,可以从文件中读取:
54955,xx,yy,zz,t
55017,xx,yy,zz,t
55020,xx,yy,zz,t
现在,由于所有行的值都相同,因此可以手动输入:
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+-54955)}{print ","","","","}'
这将给出所需的结果:
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
***
稍后添加:感谢这个线程得到了一种将时间转换为纪元的方法,这是绝对的:
Convert date to epoch time using AWK in linux
所以它会保持这样:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}'
1596201355,xx,yy,zz,t
1596201417,xx,yy,zz,t
1596201420,xx,yy,zz,t
**
稍后再次补充:
保留第一个值的方法是使用这个 awk 表达式:
| awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
所以前面解释的2种方法将保持这样:
此案例仅适用于同一天:
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+)}{print ","","","","}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
这(使用纪元)将考虑天数:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
迄今为止的最佳解决方案:将考虑使用 epoch 的天数,并将适用于任何 awk 变体,包括 BSD 变体。它还检测有多少个字段,即使只有第一个字段也会工作:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{if (NF > 1){for (i = 2; i < NF; i += 1) printf ","$i; print ","$NF} else print ""}'
file.csv:
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
结果:
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
这是UNIX环境无法轻易处理的问题。
利用 teip
.
$ teip -d, -f1 -- sh -c "date -f- +%s" < file.txt |
awk -F, 'NR==1{n=}{=-n};4' OFS=,
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
@anubhava 的原始回答(只有 2 个字段):
您可以将此 awk
与 mktime
功能一起使用。
这将输出以逗号分隔的 2 个字段:
awk 'BEGIN {
FS=OFS="," # set input and output field separators to comma
}
{
gsub(/[-:]/, " ", ) # replace - and : with a space
tm = mktime() # convert date-time string to EPOCH value
if (NR == 1) # for 1st records store this value in first
first = tm
print (tm - first), # print difference and 2nd field for each record
}' file
结果:
0,xx
62,xx
65,xx
由@smeterlink 改进
这将使用 NF 变量检测所有以逗号分隔的字段,因此即使只有第一个字段也能正常工作。这样可以混合不同数量字段的行:
get.awk:
BEGIN {
FS=OFS="," # set input and output field separators to comma
}
{
gsub(/[-:]/, " ", ) # replace - and : with a space
tm = mktime() # convert date-time string to EPOCH value
if (NR == 1) # for 1st records store this value in first
first = tm
{
printf (tm - first) # print difference
if (NF > 1) # print 2nd to last fields only if they exist
{
for (i = 2; i < NF; i += 1)
printf ","$i
print ","$NF
}
else
print "" # otherwise print newline after printf
}
}
file.csv:
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
有一个 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
我可以使用任何编程语言来完成,例如 bash、awk、sed、perl...并覆盖相同的文件或创建一个新文件。
perl -MTime::Piece -F, -lane '
BEGIN {$, = ","}
$t = Time::Piece->strptime(shift(@F), "%F %T")->epoch;
if ($. == 1) {$start = $t}
print $t - $start, @F;
' file
这是一个有效的部分答案,考虑到日期不会改变,因此被省略。
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+)}{print ","","","","}'
这将输出这个结果,它仍然没有休息第一个值,可以从文件中读取:
54955,xx,yy,zz,t
55017,xx,yy,zz,t
55020,xx,yy,zz,t
现在,由于所有行的值都相同,因此可以手动输入:
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+-54955)}{print ","","","","}'
这将给出所需的结果:
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
*** 稍后添加:感谢这个线程得到了一种将时间转换为纪元的方法,这是绝对的: Convert date to epoch time using AWK in linux 所以它会保持这样:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}'
1596201355,xx,yy,zz,t
1596201417,xx,yy,zz,t
1596201420,xx,yy,zz,t
** 稍后再次补充: 保留第一个值的方法是使用这个 awk 表达式:
| awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
所以前面解释的2种方法将保持这样: 此案例仅适用于同一天:
cat file.csv | awk -F ' ' '{print }'| awk -F ':|,' '{printf (*3600+*60+)}{print ","","","","}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
这(使用纪元)将考虑天数:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{print ","","","","}'
迄今为止的最佳解决方案:将考虑使用 epoch 的天数,并将适用于任何 awk 变体,包括 BSD 变体。它还检测有多少个字段,即使只有第一个字段也会工作:
cat file.csv | awk -F, '{ OFS = FS;command="date -d " "\"" "\"" " +%s";command | getline ;close(command);print}' | awk -F, 'NR==1{pattern=}{printf (-pattern)}{if (NF > 1){for (i = 2; i < NF; i += 1) printf ","$i; print ","$NF} else print ""}'
file.csv:
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
结果:
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
这是UNIX环境无法轻易处理的问题。
利用 teip
.
$ teip -d, -f1 -- sh -c "date -f- +%s" < file.txt |
awk -F, 'NR==1{n=}{=-n};4' OFS=,
0,xx,yy,zz,t
62,xx,yy,zz,t
65,xx,yy,zz,t
@anubhava 的原始回答(只有 2 个字段):
您可以将此 awk
与 mktime
功能一起使用。
这将输出以逗号分隔的 2 个字段:
awk 'BEGIN {
FS=OFS="," # set input and output field separators to comma
}
{
gsub(/[-:]/, " ", ) # replace - and : with a space
tm = mktime() # convert date-time string to EPOCH value
if (NR == 1) # for 1st records store this value in first
first = tm
print (tm - first), # print difference and 2nd field for each record
}' file
结果:
0,xx
62,xx
65,xx
由@smeterlink 改进
这将使用 NF 变量检测所有以逗号分隔的字段,因此即使只有第一个字段也能正常工作。这样可以混合不同数量字段的行:
get.awk:
BEGIN {
FS=OFS="," # set input and output field separators to comma
}
{
gsub(/[-:]/, " ", ) # replace - and : with a space
tm = mktime() # convert date-time string to EPOCH value
if (NR == 1) # for 1st records store this value in first
first = tm
{
printf (tm - first) # print difference
if (NF > 1) # print 2nd to last fields only if they exist
{
for (i = 2; i < NF; i += 1)
printf ","$i
print ","$NF
}
else
print "" # otherwise print newline after printf
}
}
file.csv:
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