Bash:如何替换 csv 文件中的日期并将分钟四舍五入为 4 个值之一

标签 bash awk

我有一个如下所示的 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/

相关文章:

linux - Bash 脚本每行输入 2 个具有不同输出元素的文件

bash - 我不明白 bash exec

bash - 仅按名称列出 Gitlab 运行器

linux - 使用 Linux 命令行过滤

awk - 用awk在不同行打印满足条件的行

ruby - Nginx似乎在Docker中的Sinatra应用程序上崩溃

regex - 更改 grep 正则表达式输出

bash - 限制 SLURM 中正在运行的作业数量

regex - 使用正则表达式与 grep 匹配科学形式的 float

xml - 转换仅包含特定标签的 xml