Оптимизированный способ расчета продолжительности времени в BASH - PullRequest
1 голос
/ 16 марта 2019

Я использую функцию ниже, которую я написал в 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 "%s\n" "$impacted"
}

Я вызываю эту функцию в цикле while, который построчно читает входной файл.

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

Ответы [ 2 ]

3 голосов
/ 16 марта 2019

При использовании GNU awk для функций времени это будет на несколько порядков быстрее, чем ваш цикл оболочки:

$ 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

Просмотрите страницу руководства, чтобы узнать, какой часовой пояс он использует по сравнению с часовым поясом, указанным в вашемвходной файл и как настроить его при необходимости.

1 голос
/ 16 марта 2019

Предположения:

  • «AST» и «ADT» - единственные два часовых пояса, которые можно встретить.
  • «AST» относится к UTC-4.
  • «ADT» относится к UTC-3.
  • Файл является файлом CSV.

Решение ниже имеет следующие особенности:

  • Правильно обрабатывает события вблизи изменений летнего времени.
  • Он правильно анализирует файл 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...