Вычитание времени в строках, используя awk, perl или другой однострочник

Подскажите, пожалуйста, каким способом можно решить следующую задачу с помощью однострочника?

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

Есть файл, вида:

$ cat blabla 
13:06:27.578195 blablabla
13:06:27.578243 bla bla
13:06:27.578271 bla
13:06:27.578337 zzz
13:06:27.578372 zzz zzz zzz
13:06:27.578372 zzz zzz zzz
13:07:02.224100 aaa bbb ccc

Необходимо, используя любую команду(ы) в одну строку получить вывод вида:

0 13:06:27.578195 blablabla
0.000048 13:06:27.578243 bla bla
0.000028 13:06:27.578271 bla
0.000066 13:06:27.578337 zzz
0.000035 13:06:27.578372 zzz zzz zzz
34,645728 13:07:02.224100 aaa bbb ccc

Кажется, что это можно сделать с помощью awk, но у меня не получилось.


Ответы (2 шт):

Автор решения: extrn

Не лишенный недостатков, но все же способ

$ perl -ane '$c = `date +%s.%N -d $F[0]`; printf "%.6f %s", $c - ($p or $c), $_; $p = $c' < log.txt
0.000000 13:06:27.578195 blablabla
0.000048 13:06:27.578243 bla bla
0.000028 13:06:27.578271 bla
0.000066 13:06:27.578337 zzz
0.000035 13:06:27.578372 zzz zzz zzz
0.000000 13:06:27.578372 zzz zzz zzz
34.645728 13:07:02.224100 aaa bbb ccc

Имейте в виду, что на границе суток смещение получится отрицательным.

→ Ссылка
Автор решения: aleksandr barakin

например, с помощью программы gnu/awk.

разбиваем первое слово на части по разделителю :, преобразуем минуты-часы в секунды (умножая последовательно на 60).

если полученное значение меньше предыдущего, предполагаем, что это новые сутки, и вычитаем из предыдущего значения количество секунд в сутках.

awk 'BEGIN{ p = 0 }
{
  split($1, a, ":");
  s = 0;
  for (i = 1; i <= length(a); i++) {
    s = s * 60 + a[i]
  };
  if (p == 0) {
    printf "0 "
  } else {
    if (p > s) {
      p = p - 60 * 60 * 24;
    }
    printf "%.6f ", s - p
  };
  p = s;
  print $0
}'

из набора данных:

13:06:27.578195 blablabla
13:06:27.578243 bla bla
13:06:27.578271 bla
13:06:27.578337 zzz
13:06:27.578372 zzz zzz zzz
13:06:27.578372 zzz zzz zzz
13:07:02.224100 aaa bbb ccc
01:07:02.224109 новый день

получается такой:

0 13:06:27.578195 blablabla
0.000048 13:06:27.578243 bla bla
0.000028 13:06:27.578271 bla
0.000066 13:06:27.578337 zzz
0.000035 13:06:27.578372 zzz zzz zzz
0.000000 13:06:27.578372 zzz zzz zzz
34.645728 13:07:02.224100 aaa bbb ccc
43200.000009 01:07:02.224109 новый день

чтобы получить однострочник, просто убираем все пробелы (кроме как в аргументе функции printf) и новые строки:

awk 'BEGIN{p=0}{split($1,a,":");s=0;for(i=1;i<=length(a);i++){s=s*60+a[i]};if(p==0){printf"0 "}else{if(p>s){p=p-60*60*24;}printf"%.6f ",s-p};p=s;print$0}'
→ Ссылка