LINUX.ORG.RU

Утилита подстветки изменений значений от строки к строке

 , , ,


0

1

День добрый.

Есть текстовый лог в формате CSV.

В столбцах — счетчики (в том числе времени), показания от датчиков, идентификаторы состояний в виде одной буквы.
(Очевидно, очень похоже на NMEA).

Все значения обычно (но не всегда) либо монотонно растут (счетчики), либо незначительно колеблются вокруг какой-то константы (датчики).

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

В идеале, если катать губу, утилита вообще должна понимать поведение полей по статистике, например,
«ага, обычно этот счетчик растет раз в 5 строк, а здесь не растет уже 6 строк, надо подсветить красным сей факт».

★★

Загони в lo writer и построй график

Или расцвети через условное форматирование.

anonymous
()

А графические аналоги diff чем не устраивают? Например, kdiff3, fldiff и т. д. Они, конечно, не будут подсвечивать разным цветом в зависимости от дельты, но как-то подсветят. Только надо 2 или 3 файла создать, содержащие последние строки, которые сравниваются. Но це, имхо, дело техники.

aureliano15 ★★
()
Ответ на: комментарий от Deleted

для известного форматам это вообще пишется руками

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

Tayler ★★
() автор топика
Ответ на: комментарий от anonymous

Загони в lo writer и построй график

График, да, согласен, вариант. Скорее всего так и буду делать.
Хотя если есть что-то готовое простое, консольное, да еще работающее на ходу, будет интересно узнать о таком.

Tayler ★★
() автор топика
Последнее исправление: Tayler (всего исправлений: 1)
Ответ на: комментарий от aureliano15

Они, конечно, не будут подсвечивать разным цветом в зависимости от дельты, но как-то подсветят.

Я грубо говоря ищу ошибки, отклонения. Просто «как-то подсветить» не выделит интересную информацию мне.

Tayler ★★
() автор топика
Ответ на: комментарий от Tayler

Я грубо говоря ищу ошибки, отклонения. Просто «как-то подсветить» не выделит интересную информацию мне.

Ну тогда можно написать простенький скрипт на awk, например.

очень похоже на NMEA

Ну пусть будет похоже на NMEA. Точно я NMEA не помню, к тому же там много разных форматов, но допустим есть у нас лог такого формата:

НОМЕР_ЦЕЛИ ШИРОТА ДОЛГОТА КУРС СКОРОСТЬ ДАТА ВРЕМЯ

Допустим также, что мы сопровождаем только одну цель (N цели не меняется) и отслеживаем изменения широты, долготы, курса и скорости.

При изменении одного из этих параметров по сравнению с предыдущим, он будет отображаться зелёным. Кроме того, цель у нас всегда находится к северу от экватора и к востоку от гринвича. Соответственно, S в широте и W в долготе мы считаем ошибкой и отображаем координату красным. Ну и отслеживаем мы тихоход, а не ракету, поэтому скорость, большую или равную 100 узлам тоже считаем ненормальной и отображаем красным. Скрипт может выглядеть примерно так:

#!/usr/bin/awk -f

BEGIN {
 red_color="\033[01;31m";
 green_color="\033[01;32m";
 default_color="\033[00m";
}

{
 if(course!="")
  prev_course=course;
 if(speed!="")
  prev_speed=speed;
 if(lat_dig!="")
  prev_lat_dig=lat_dig;
 if(lat_let!="")
  prev_lat_let=lat_let;
 if(lon_dig!="")
  prev_lon_dig=lon_dig;
 if(lon_let!="")
  prev_lon_let=lon_let;

 ntarget=$1;
 lat=$2;
 lon=$3;                                                                                                                                                                
 course=$4;                                                                                                                                                             
 speed=$5;
 dt=$6;
 tm=$7;
 lat_dig=substr(lat,1,length(lat)-1);
 lat_let=substr(lat,length(lat));
 lon_dig=substr(lon,1,length(lon)-1);
 lon_let=substr(lon,length(lon));
 printf("%s %s%s%s %s%s%s %s%s%s %s%s%s %s %s\n",
          ntarget,
          lat_let!="N" ? red_color : (prev_lat_dig!=lat_dig ? green_color : ""), lat, default_color,
          lon_let!="E" ? red_color : (prev_lon_dig!=lon_dig ? green_color : ""), lon, default_color,
          prev_course!=course ? green_color : "", course, default_color,
          speed >= 100 ? red_color : (prev_speed!=speed ? green_color : ""), speed, default_color,
          dt, tm);
}

А вот обрабатываемый лог:

1 44.22N 33.95E 180 20 2017-06-29 06:00
1 44.20N 33.95E 180 20 2017-06-29 06:03
1 44.19N 33.97E 180 20 2017-06-29 06:06
1 44.17S 33.98E 180 20 2017-06-29 06:09
1 44.16N 34.00W 180 20 2017-06-29 06:12
1 44.14N 33.98E 180 20 2017-06-29 06:15
1 44.10N 33.95E 180 100 2017-06-29 06:18
1 44.10N 33.95E 0 0 2017-06-29 06:21
1 44.10N 33.95E 0 0 2017-06-29 06:24

Делаем скрипт исполняемым и запускаем:

chmod a+x nmea_diff.awk
./nmea_diff.awk < nmea.log

Если лог большой, то можно запустить через фильтр more (less проигнорирует все терминальные esc-последовательности, с помощью которых задаются цвета, отобразив их как обычные символы) либо вместо esc-последовательностей вставлять html-теги <font color=...> и смотреть в браузере.

Если надо отслеживать только отклонения, начиная с какой-то дельты, то это тоже не сложно. Если надо сравнивать, не превосходит ли отклонение какую-то среднюю величину последних N записей, то это чуток посложнее: придётся сохранять массив этих записей, - но тоже реализуемо. Так же, как отслеживание нескольких целей (надо сохранять массив целей и по каждой считать дельты отдельно).

Если надо выводить лог постоянно по мере записи в него новых строк, то и это несложно реализовать примерно таким bash-скриптом:

#!/bin/bash

nlines=0;
while true;
  do
    nprev=$nlines;
    if [ $nprev -gt 0 ];
      then
         let nprev-=1;
    fi;
    nlines=$(wc -l < *.log);
    if [ $nlines -gt $nprev ];
      then
         let d=$nlines-$nprev;
         cat *.log | tail -n $d | ./nmea_diff.awk;
    fi;
    sleep 1;
  done

Только в этом случае скрипт awk должен выводить всё со второй строки, иначе при добавлении новой строки бывшая последняя будет повторяться (let nprev-=1). А если не уменьшать nprev, то при добавлении строк awk-скрипт будет читать их как первые, не сравнивая с предыдущими. В общем, этот вариант нуждается в небольшом допиливании.

График, да, согласен, вариант. Скорее всего так и буду делать.
Хотя если есть что-то готовое простое, консольное, да еще работающее на ходу, будет интересно узнать о таком.

Утилита gnuplot.

Например, чтобы построить график зависимости широты от времени в минутах (без учёта даты) из приведённого выше лога, в командной строке gnuplot'а в интерактивном режиме надо ввести:

plot "< cat nmea.log | awk '{print substr($7,1,2)*60+substr($7,4,2), substr($2,0,5)}'" using 1:2 with lines;

А вот трёхмерный график изменения широты и долготы со временем:

set xlabel "latitude"; set ylabel "longtitude"; set zlabel "time"; splot "< cat nmea.log | awk '{print substr($2,0,5), substr($3,0,5), substr($7,1,2)*60+substr($7,4,2)}'" using 1:2:3 with lines ti "Latitude, Longtitude, Time"

А вот то же самое в пакетном режиме (я добавил pause, чтоб окно вывода не пропадало мгновенно):

gnuplot -e "set xlabel \"latitude\"; set ylabel \"longtitude\"; set zlabel \"time\"; splot \"< cat nmea.log | awk '{print substr(\$2,0,5), substr(\$3,0,5), substr(\$7,1,2)*60+substr(\$7,4,2)}'\" using 1:2:3 with lines ti \"Latitude, Longtitude, Time\"; pause -1"

Утилита может работать как в интерактивном, так и в пакетном режиме, выводя графики как на экран, так и в графические файлы разных форматов. Может строить графики и диаграммы разного вида, 2-х и 3-х мерные, несколько графиков на одном экране/рисунке и т. д. Возможностей у неё много, см. доку. А если работает апач, то графики можно подсовывать ему. Или даже просто перезаписывать один и тот же файл с графиком и обновлять его в браузере (локальный вариант без апача). И не надо ничего самому рисовать, всё легко автоматизируется.

aureliano15 ★★
()
Ответ на: комментарий от aureliano15

Только в этом случае скрипт awk должен выводить всё со второй строки, иначе при добавлении новой строки бывшая последняя будет повторяться (let nprev-=1). А если не уменьшать nprev, то при добавлении строк awk-скрипт будет читать их как первые, не сравнивая с предыдущими. В общем, этот вариант нуждается в небольшом допиливании.

Сорри, ступил. Ничего допиливать не надо, если сделать так:

#!/bin/bash

(nlines=0;
while true;
  do
    nprev=$nlines;
    nlines=$(wc -l < nmea.log);
    if [ $nlines -gt $nprev ];
      then
         let d=$nlines-$nprev;
         cat nmea.log | tail -n $d
    fi;
    sleep 1;
  done) | ./nmea_diff.awk

aureliano15 ★★
()

Похоже на принцип работы watch, вот только оно для терминального вывода и без разной подсветки.

Deleted
()
Ответ на: комментарий от aureliano15

less проигнорирует все терминальные esc-последовательности, с помощью которых задаются цвета

Зато «less -r» или «less -R» даст цветной вывод.

bormant ★★★★★
()
Ответ на: комментарий от bormant

Зато «less -r» или «less -R» даст цветной вывод.

Вот об этом я не нал. Спасибо за информацию. Очень полезная опция в некоторых случаях.

aureliano15 ★★
()
Ответ на: комментарий от RazrFalcon

Достаточно консольного colordiff.

colordiff выводит то же, что и diff, только подсвечивает, и этот вывод более удобен для машинной обработки patch'ем или другими утилитами, чем для изучения человеком. А графические утилиты просто выводят строки с подсветкой различий. Имхо, для визуального отслеживания изменений удобнее.

aureliano15 ★★
()
Ответ на: комментарий от aureliano15

Если полезная, можно ее (-R безопаснее) добавить в переменную окружения LESS - будет нужное поведение автоматом.

bormant ★★★★★
()
Ответ на: комментарий от bormant

можно ее (-R безопаснее) добавить в переменную окружения LESS

Спасибо за информацию. Сейчас посмотрел man, там ещё можно LESSANSIENDCHARS и LESSANSIMIDCHARS для большей безопасности установить.

aureliano15 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.