Bash 查找时间戳之前的最后一个条目

标签 bash grep

我有一个采用这种格式的 .csv 文件;

myfile.csv

**Date,Timestamp,Data1,Data2,Data3,Data4,Data5,Data6**  
20130730,22:08:51.244,APPLES,Spain,67p,blah,blah  
20130730,22:08:51.244,PEARS,Spain,32p,blah,blah  
20130730,22:08:51.708,APPLES,France,102p,blah,blah  
20130730,22:10:62.108,APPLES,Spain,67p,blah,blah  
20130730,22:10:68.244,APPLES,Spain,67p,blah,blah  

我希望输入一个时间戳,该时间戳很可能与文件中的毫秒不完全匹配,并找到与特定 grep 搜索匹配的前一行。

所以例如类似的东西;

cat myfile.csv | grep 'Spain' | grep 'APPLES' | grep -B1 "22:09"

应该返回

20130730,22:08:51.244,APPLES,Spain,67p,blah,blah

但到目前为止,我只能让它在 grep 中使用精确的时间戳。有没有办法让它将这些视为时间序列? (我猜这就是问题所在 - 它正在尝试纯粹的模式匹配,而不是无理地未能找到一个)

最佳答案

我还有一个使用 awk 的奇特解决方案:

awk -F ',' -v mytime="2013 07 30 22 09 00" '
  BEGIN {tlimit=mktime(mytime); lastline=""}
  {
    l_y=substr($1,0,4); l_m=substr($1,4,2); l_d=substr($1,6,2);
    split($2,l_hms,":"); l_hms[3]=int(l_hms[3]);
    line_time=mktime(sprintf("%d %d %d %d %d %d", l_y, l_m, l_d, l_hms[1], l_hms[2], l_hms[3]));
    if (line_time>tlimit) exit; lastline=$0;
  }
  END{if lastline=="" print $0; else print lastline;}' myfile.csv

它的工作原理是使用 awk 的时间函数 mktime 从每一行生成时间戳。 。我还假设 $1 是日期。

在第一行,您必须提供所需时间限制的时间戳(此处我选择2013 07 30 22 09 00)。您必须按照 mktime 使用的格式编写它:YYYY MM DD hh mm ss。您以构成时间限制的时间戳开始 awk 语句。然后,对于每一行,您可以从 $1(第 4 行)获取年、月和日,然后从 $2(第 5 行)获取确切的小时。由于 mktime 仅需要整秒,因此我截断了秒数(您可以使用 int(l_hms[3]+0.5) 将其四舍五入)。在这里,您可以执行任何您想要近似时间戳的操作,例如丢弃秒数。在第 6 行,我根据提取的六个日期字段制作了时间戳。最后,在第 7 行,我比较时间戳并在达到时间限制时转到结束。正如您想要的前一行,我将该行存储到变量 laSTLine 中。退出时,我打印 laSTLine;如果达到第一行的时间限制,我会打印第一行。

此解决方案适用于您的示例文件,并且适用于您提供的任何日期。您只需以正确的格式提供日期限制即可!

编辑

我意识到mktime是没有必要的。如果假设 $1 是写为 YYYYMMDD 的日期,则可以将日期作为数字进行比较,然后与时间进行比较(使用 split 提取,按照其他答案中的方式重新构建为数字)。在这种情况下,您可以按照所需的格式提供时间限制,并在 BEGIN block 中恢复正确的日期和时间限制。

关于Bash 查找时间戳之前的最后一个条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18404564/

相关文章:

bash - 如何在单独的自动变量中获得这些结果?

regex - 如何过滤 Bash 正则表达式(Linux)中除一个之外的所有值?

bash - `echo . `( echo 点)是什么意思?

bash - 使用另一个文件中的指定顺序对文件中的行进行排序

linux - 尝试运行扩展 GIT 的脚本

regex - 使用grep regex解析文本从文件中的多行文本中提取文本

linux - 为什么在这种情况下 grep 不返回整行?

unix - 仅打印匹配记录后开始的匹配标题字段

linux - 如何使用 BASH 比较两个文本文件的相同文本?

bash - 在一个命令中通过 xargs 传送两个文件名(带空格)