Оболочка Linux: обнаружение изменений состояния в файле журнала CSV - PullRequest
0 голосов
/ 28 апреля 2018

Это мой автоматически сгенерированный лог-файл (непрерывная минутная проверка моей интернет-линии):

$ cat log.csv

2018-04-27,23:37,OK
2018-04-27,23:38,OK
2018-04-27,23:39,OK
2018-04-27,23:40,ERROR
2018-04-27,23:41,ERROR
2018-04-27,23:42,OK
2018-04-27,23:43,OK
2018-04-27,23:44,OK
2018-04-27,23:45,OK

Я пытаюсь сделать его более удобным для чтения с помощью сценариев некоторого метода интерпретации, который зависит от состояния 3-го поля (состояние строки: ОК / ОШИБКА), а удаляет последовательные значения , своего рода сценарий оболочки, который показывает только начальное значение и изменение состояния для интернет-линии, преобразуя вышеприведенный журнал в:

2018-04-27,23:37,OK
2018-04-27,23:40,ERROR
2018-04-27,23:42,OK

Это будет означать:

2018-04-27,23:37,Entered Status OK
2018-04-27,23:40,Entered Status ERROR
2018-04-27,23:42,Entered Status OK

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

Предполагая, что файл журнала может быть очень длинным (рассмотрим месяцы записи в одну минуту), что может быть правильным (эффективным) методом для написания этой «интерпретации» в оболочке Linux ?

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

Дополнительные данные :

  • Подобный (но не тот же самый) вопрос (тоже заданный мной) здесь .

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Опция 1. Команда Bash uniq достаточна, когда начало строки журнала имеет одинаковую длину или когда разделитель между полями либо пробел, либо табуляция.

uniq -s 17 log.csv

uniq отфильтровывает соседние совпадающие строки, а флаг -s 17 заставляет игнорировать первые 17 символов каждой строки, составляющих временную метку.

uniq -f 2 log.csv

-f 2 заставляет uniq игнорировать первые два поля. К сожалению, нет способа изменить разделитель по умолчанию с пробела на что-то еще.

Опция 2. tr и uniq будут работать для простых случаев, когда разделитель легко переключается.

# tab is inserted with CTRL+V followed by TAB
tr ',' '    ' < log.csv | uniq -f 2

tr - это сокращение от translate, и все вхождения первого аргумента будут преобразованы во второй аргумент (в данном случае из табуляции). tr работает с потоком в качестве ввода.

Опция 3. sed и uniq будут работать для более сложных случаев, когда содержимое журнала может содержать сам разделитель.

sed 's/,/\t/;s/,/\t/' log.csv | uniq -f 2

sed означает сокращение для редактора потоков и заменит первые два вхождения запятой на вкладку (sed позволяет использовать \ t). sed 's/,/\t/' log.csv заменит только первое вхождение, поэтому один и тот же поиск повторяется дважды, добавляя один и тот же шаблон поиска и замены, дважды разделенные точкой с запятой.

Подробнее об использовании uniq:

man uniq
uniq --help
0 голосов
/ 28 апреля 2018

Метод AWK:

awk -F "," '$3==last{next} {last=$3} {print $0}' log.csv

Это выводит:

2018-04-27,23:37,OK
2018-04-27,23:40,ERROR
2018-04-27,23:42,OK

Как это работает :

  • -F "," для запятой в качестве разделителя полей.
  • $3==last{next} игнорирует любую строку, где третье поле равно переменной last: команда next говорит awk пропустить все оставшиеся команды и начать все заново со следующей строки.
  • last=$3 сохраняет третье поле (OK / ERROR) в переменной last.
  • {print $0} означает печать текущей строки.

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

Спасибо John1024 за эту тему

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...