优化的方法来计算bash中的持续时间



我正在使用以下我在bash中编写的以计算时间持续时间的函数,并确定持续时间是否超过5分钟,它返回是,否则。它正常工作,但是我正在处理的文件是巨大的(数百万行),并且完成工作需要很长时间。我正在寻找一些优化的方法。

datediff() {
d2=$(date -d "$2" +%s)
d1=$(date -d "$3" +%s)
secs=$((d1 - d2))
impacted="no"
if [ $(($secs / 300 )) -gt 0 ]
  then
  impacted="yes"
fi
printf "%sn" "$impacted"
}

我正在以一行读取输入文件。

读取此功能。
while IFS=',' read -r line;
do
   IFS=',' read source almapear almclear <<< "$line"
   echo $line, $(datediff $source "$almapear" "$almclear")
done < "$1" | tee -a output_$1

下面是示例输入文件,其中包含源名称,警报出现时间,然后清除警报时间:

D00O0:SOURCE3,Mon Oct 01 16:02:35 AST 2018,Mon Oct 01 16:04:19 AST 2018
D00O0:SOURCE3,Mon Oct 08 08:53:17 AST 2018,Mon Oct 08 08:54:57 AST 2018
D00O1:SOURCE3,Mon Oct 15 09:25:14 AST 2018,Mon Oct 15 09:26:59 AST 2018
D00O1:SOURCE3,Mon Oct 15 16:56:58 AST 2018,Mon Oct 15 17:58:41 AST 2018
D00O1:SOURCE3,Mon Oct 22 08:56:48 AST 2018,Mon Oct 22 09:58:31 AST 2018
D00O1:SOURCE3,Sat Oct 06 09:17:42 AST 2018,Sat Oct 06 09:19:24 AST 2018
D00O1:SOURCE3,Sat Oct 13 09:11:05 AST 2018,Sat Oct 13 09:12:47 AST 2018
D00O1:SOURCE3,Sat Oct 20 09:51:40 AST 2018,Sat Oct 20 09:53:23 AST 2018
D00O0:SOURCE3,Sat Oct 27 09:15:32 AST 2018,Sat Oct 27 09:17:11 AST 2018
D00O0:SOURCE3,Sat Sep 29 10:05:58 AST 2018,Sat Sep 29 11:07:43 AST 2018
D00O0:SOURCE3,Sun Oct 14 08:48:57 AST 2018,Sun Oct 14 09:50:43 AST 2018
D00O0:SOURCE3,Sun Oct 14 16:04:19 AST 2018,Sun Oct 14 16:06:00 AST 2018
D00O0:SOURCE3,Sun Oct 21 06:17:34 AST 2018,Sun Oct 21 06:19:17 AST 2018
D00O0:SOURCE3,Sun Oct 21 16:15:18 AST 2018,Sun Oct 21 17:17:00 AST 2018
D00O0:SOURCE3,Sun Oct 28 09:39:09 AST 2018,Sun Oct 28 09:40:47 AST 2018

以下是所需的输出:

D00O0:SOURCE3,Mon Oct 01 16:02:35 AST 2018,Mon Oct 01 16:04:19 AST 2018,no
D00O0:SOURCE3,Mon Oct 08 08:53:17 AST 2018,Mon Oct 08 08:54:57 AST 2018,no
D00O1:SOURCE3,Mon Oct 15 09:25:14 AST 2018,Mon Oct 15 09:26:59 AST 2018,no
D00O1:SOURCE3,Mon Oct 15 16:56:58 AST 2018,Mon Oct 15 17:58:41 AST 2018,yes
D00O1:SOURCE3,Mon Oct 22 08:56:48 AST 2018,Mon Oct 22 09:58:31 AST 2018,yes
D00O1:SOURCE3,Sat Oct 06 09:17:42 AST 2018,Sat Oct 06 09:19:24 AST 2018,no
D00O1:SOURCE3,Sat Oct 13 09:11:05 AST 2018,Sat Oct 13 09:12:47 AST 2018,no
D00O1:SOURCE3,Sat Oct 20 09:51:40 AST 2018,Sat Oct 20 09:53:23 AST 2018,no
D00O0:SOURCE3,Sat Oct 27 09:15:32 AST 2018,Sat Oct 27 09:17:11 AST 2018,no
D00O0:SOURCE3,Sat Sep 29 10:05:58 AST 2018,Sat Sep 29 11:07:43 AST 2018,yes
D00O0:SOURCE3,Sun Oct 14 08:48:57 AST 2018,Sun Oct 14 09:50:43 AST 2018,yes
D00O0:SOURCE3,Sun Oct 14 16:04:19 AST 2018,Sun Oct 14 16:06:00 AST 2018,no
D00O0:SOURCE3,Sun Oct 21 06:17:34 AST 2018,Sun Oct 21 06:19:17 AST 2018,no
D00O0:SOURCE3,Sun Oct 21 16:15:18 AST 2018,Sun Oct 21 17:17:00 AST 2018,yes
D00O0:SOURCE3,Sun Oct 28 09:39:09 AST 2018,Sun Oct 28 09:40:47 AST 2018,no

带有GNU尴尬以进行时间功能,这将比您的外壳循环快的数量级:

$ cat tst.awk
BEGIN {
    FS = "[, :]"
    OFS = ","
    split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",tmp)
    for (i in tmp) {
        mth[tmp[i]] = i
    }
    maxSecs = 5 * 60
}
{
    begSecs = mktime($10" "mth[$4]" "$5" "$6" "$7" "$8)
    endSecs = mktime($18" "mth[$12]" "$13" "$14" "$15" "$16)
    print $0, ( (endSecs - begSecs) > maxSecs ? "yes" : "no" )
}
$ awk -f tst.awk file
D00O0:SOURCE3,Mon Oct 01 16:02:35 AST 2018,Mon Oct 01 16:04:19 AST 2018,no
D00O0:SOURCE3,Mon Oct 08 08:53:17 AST 2018,Mon Oct 08 08:54:57 AST 2018,no
D00O1:SOURCE3,Mon Oct 15 09:25:14 AST 2018,Mon Oct 15 09:26:59 AST 2018,no
D00O1:SOURCE3,Mon Oct 15 16:56:58 AST 2018,Mon Oct 15 17:58:41 AST 2018,yes
D00O1:SOURCE3,Mon Oct 22 08:56:48 AST 2018,Mon Oct 22 09:58:31 AST 2018,yes
D00O1:SOURCE3,Sat Oct 06 09:17:42 AST 2018,Sat Oct 06 09:19:24 AST 2018,no
D00O1:SOURCE3,Sat Oct 13 09:11:05 AST 2018,Sat Oct 13 09:12:47 AST 2018,no
D00O1:SOURCE3,Sat Oct 20 09:51:40 AST 2018,Sat Oct 20 09:53:23 AST 2018,no
D00O0:SOURCE3,Sat Oct 27 09:15:32 AST 2018,Sat Oct 27 09:17:11 AST 2018,no
D00O0:SOURCE3,Sat Sep 29 10:05:58 AST 2018,Sat Sep 29 11:07:43 AST 2018,yes
D00O0:SOURCE3,Sun Oct 14 08:48:57 AST 2018,Sun Oct 14 09:50:43 AST 2018,yes
D00O0:SOURCE3,Sun Oct 14 16:04:19 AST 2018,Sun Oct 14 16:06:00 AST 2018,no
D00O0:SOURCE3,Sun Oct 21 06:17:34 AST 2018,Sun Oct 21 06:19:17 AST 2018,no
D00O0:SOURCE3,Sun Oct 21 16:15:18 AST 2018,Sun Oct 21 17:17:00 AST 2018,yes
D00O0:SOURCE3,Sun Oct 28 09:39:09 AST 2018,Sun Oct 28 09:40:47 AST 2018,no

查找MAN页面,以查看使用输入文件中指定的时区以及在必要时如何调整该时区的时区。

假设:

  • " ast"one_answers" adt"是唯一可以遇到的区域。
  • " ast"是指UTC-4。
  • " ADT"是指UTC-3。
  • 该文件是CSV文件。

下面的解决方案具有以下功能:

  • 它正确处理DST附近的事件。
  • 它正确解析了CSV文件。
  • 它正确生成了CSV文件。

没有现有的解决方案(包括您自己的解决方案)可以声称具有前两个功能。

#!/usr/bin/perl
use strict;
use warnings;
use feature qw( state );
use DateTime::Format::Strptime qw( );
use Text::CSV_XS               qw( );
sub parse_dt_str {
   my ($dt_str) = @_;
   state $format = DateTime::Format::Strptime->new(
      pattern => "%a %b %d %H:%M:%S %z %Y",
      locale  => "en",
   );
   $dt_str =~ s/b(AST|ADT)b/ $1 eq "AST" ? "-0400" : "-0300" /e;
   return $format->parse_datetime($dt_str);
}
my $csv = Text::CSV_XS->new({ auto_diag => 2, binary => 1, quote_space => 0 });
while ( my $row = $csv->getline(*ARGV) ) {
   my $dt1 = parse_dt_str($row->[1]);
   my $dt2 = parse_dt_str($row->[2]);
   if ($dt1 && $dt2) {
      $row->[3] = $dt2->epoch - $dt1->epoch > 5*60 ? "yes" : "no";
   } else {
      $row->[3] = "???";
   }
   $csv->say(*STDOUT, $row);
}

最新更新