我有一个如下所示的 csv 文件:
datetime,nameval1,nameval2,nameval3,...,namevalx
2015/03/16 19:55:10,a,b,c,...,x
2015/03/16 19:30:30,a1,b1,c1,...,x1
2015/03/16 19:30:50,a2,b2,c2,...,x2
我需要修改日期,它是此 csv 文件中第二行开始的第一个值,以便将分钟四舍五入为 00、15、30、45、60(如果分钟为 60,则小时需要增加 1 并且分钟值返回 00,如果这是第 23 天的最后一个小时,那么另外这一天需要增加 1)。
我发现 awk 命令可能正在帮助我实现我想做的事情。我已简化为仅基于分钟舍入值的简单测试 - 如果分钟调整值为 60,则我将 $5 改回 00。
awk 'BEGIN {FS="[,/ :]"; OFS=","} {
if ($1=="datetime")
{
print
}
else
{
min=(int(($5+15/2)/15))*15
if(min == 60)
$5="00"
date=$1 "/" $2 "/" $3 " " $4 ":" $5 ":" $6
$1=$2=$3=$4=$5=$6=""
print date $0
}
;}' ./file.csv
我遇到了一些问题:
1) 这是我得到的一行结果的示例,其中我没有设法正确合并日期和/或我需要 awk 仅打印其余起始列 $7:
2014/03/16 19:00:50,,,,,,a,b,c,...,x
2) 我使用 awk 拆分 csv 文件的方式并不是我所需要的,因为文件中的其他变量可能包含/或空格。我只需要使用逗号进行拆分,然后使用这 3 个字符 [/:] 之一将日期时间进一步拆分为其组件年/月/日/小时/分钟/秒。
3) 我需要通过一个 if 语句来避免触及我在这里所做的文件的第一行,如果 awk 也可以做的更简单,我会使用
谢谢!
最佳答案
令人高兴的是,您的日期格式只需稍作调整即可与 mktime
一起使用, 所以使用 GNU awk:
awk -F, 'BEGIN { OFS = FS } NR != 1 { gsub(/[/:]/, " ", $1); ts = mktime($1); ts = int((ts + 450) / 900) * 900; $1 = strftime("%Y/%m/%d %H:%M:%S", ts) } 1' filename
它的核心是 mktime
函数,它将适当格式化的时间戳转换为自纪元(1970-01-01 00:00:00 UTC)以来的秒数。有了这个数字,四舍五入到四分之一小时很容易,而且碰巧的是,mktime
期望的格式是带有 /
和 的时间戳:
替换为空格。所以:
BEGIN { # In the beginning:
OFS = FS # set the output field separator to
# the same as the input field sep.
# so the output is delimited the
# same way as the input
}
NR != 1 { # Unless this is the first line
gsub(/[/:]/, " ", $1) # replace / and : in the first field
# with spaces
ts = mktime($1) # calculate seconds since Epoch
ts = int((ts + 450) / 900) * 900 # round to quarter hour
$1 = strftime("%Y/%m/%d %H:%M:%S", ts) # write back suitably formatted
# time stamp
}
1 # then print.
这里最大的警告是这些东西的大部分都是特定于 GNU 的,因此您需要使用 awk 的 GNU 风格来运行它。您的包管理器可能会称它为 gawk
。
关于Bash:如何替换 csv 文件中的日期并将分钟四舍五入为 4 个值之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29724693/