Вычисление разницы во времени между двумя датами с помощью linux

#linux #bash #for-loop #awk

Вопрос:

Доброе утро. У меня есть два текстовых файла с именем a.txt и b.txt , которые содержат данные в следующем формате, как показано ниже

 year mn dt hr:mn:sec
xxxx-xx-xx xx:xx:xx.xxxxxx
 

Мой a.txt файл является

 2019-01-01 00:58:49.925000
2019-01-01 01:48:39.665000


2019-01-01 15:42:18.955000

2019-01-01 18:40:49.915000
2019-01-01 18:47:00.735000

2019-01-01 21:07:49.255000
2019-01-01 21:52:29.055000
2019-01-02 03:19:54.955000
2019-01-02 07:41:27.845000
2019-01-02 18:52:32.995000
 

И b.txt файл содержит

 2019-01-01 00:58:50.565000
2019-01-01 01:48:39.915000
2019-01-01 04:09:53.705000
2019-01-01 06:28:07.515000

2019-01-01 15:43:13.455000
2019-01-01 18:40:53.255000
2019-01-01 18:47:04.005000
2019-01-01 18:47:03.975000
2019-01-01 21:07:53.725000
2019-01-01 21:52:37.195000

2019-01-02 07:41:34.255000
2019-01-02 19:41:08.865000
 

Кроме того, каждый из текстовых файлов (a.txt и b.txt) содержит 14 строк, включая пробел.

Теперь я хочу рассчитать разницу во времени между каждой строкой ( a.txt-b.txt ) в секундах, и я хочу добавить строки в новый текстовый файл c.txt который должен содержать только строки с разницей во времени от 3 до 18 секунд.

Я сделал что-то вроде следующего:

 #!/bin/sh
a=`cat a.txt`
b=`cat b.txt`
awk '{print $a-$b}' 
 

Комментарии:

1. Что должно произойти, если одна из дат пуста? Например, в третьей строке ваших файлов примеров.

2. А как насчет пустых строк? Как вы хотите их различать? a.txt имеет 10 дат, тогда b.txt как имеет 12 дат.

3. если пустые результаты должны быть равны нулю

4. Что вы подразумеваете под пустыми результатами ? пустые строки? Предполагается, что даты для пустых строк равны 0? Или просто верните 0?

5. да..я предполагаю, что для пустых строк значение равно нулю, так как значение строк не показывает, что его результаты должны быть равны нулю

Ответ №1:

Использование GNU awk для mktime() на основе одной из возможных интерпретаций вашего вопроса:

 $ cat tst.awk
!NF { next }
{ gsub(/[-:]/," ") }
NR==FNR {
    file1[NR] = $0
    next
}
FNR in file1 {
    diff = mktime($0) - mktime(file1[FNR])
    if ( (3 <= diff) amp;amp; (diff <= 18) ) {
        print diff
    }
}
 
 $ awk -f tst.awk a.txt b.txt
4
4
4
8
7
 

Очевидно, просто добавьте > c.txt , чтобы перенаправить вывод.

Если это не то, что вам нужно, отредактируйте свой вопрос, чтобы уточнить свои требования и предоставить ожидаемый результат с учетом опубликованного вами образца ввода.

Ответ №2:

Преобразуйте каждую дату в время unix с помощью date -d "2019-01-01 …" %s . Затем вычтите время unix. При этом учитываются только целые секунды. Ваши даты включают доли секунд. Если вы тоже хотите использовать дроби, измените %s на %s.%N .

Следующий сценарий включает в себя все ваши дополнительные требования, см. раздел комментариев к этому ответу.

 paste a.txt b.txt |
awk '
function inSecs(date) {
  cmd = "date -d ""date""  %s"
  cmd | getline unixTime
  close(cmd)
  return unixTime
}
{
  if (NF == 4) {
    diff = inSecs($1" "$2) - inSecs($3" "$4)
    if (3 <= diff amp;amp; diff <= 18)
      print $1 " " diff "sec"
  } 
}'
 

Комментарии:

1. но несколько раз в a.txt строка пропущена, в то время как в b.txt строка, присутствующая в этом случае, я хочу, чтобы вывод был равен нулю…пожалуйста, вы можете один раз изменить свой сценарий..

2. Однако мне нужно, чтобы дата была добавлена в формате гггг-мн-день до результатов, я имею в виду, что результаты должны быть примерно такими: 2019-01-01 1 сек

3. @dtutub Если вы задаете вопрос, пожалуйста, сделайте его полным, а не добавляйте в него что-то новое после каждого ответа. Тем не менее, я не понимаю ваш ожидаемый формат вывода. Если вы вычтете две даты 2019-01-02 03:04:05.0 , а 2019-01-01 01:01:01.0 затем какой будет ожидаемый результат?

4. пожалуйста, обновите ответ, сэр, так как мне также нужна дата. я сделал что-то вроде ошибки печати даты($1) — ошибки($2) …это не дает результатов, как я хотел бы

5. я думаю, что в моем случае даты похожи, меняется только время