Как разделить файл журнала в bash в зависимости от времени - PullRequest
1 голос
/ 03 марта 2020

У меня есть простой файл журнала с отметкой времени в миллисекундах, как этот:

[02/03/2020 07:53:58.859000] 5
[02/03/2020 07:53:58.935300] 2
[02/03/2020 10:04:50.355600] 0
[02/03/2020 10:04:51.028900] 1
[02/03/2020 10:38:13.468200] 6

И я хочу добиться лучшей читаемости, так что + -2 секунды отделяйте журналы по тире, как этот:

[02/03/2020 07:53:58.859000] 5
[02/03/2020 07:53:58.935300] 2
------------------------------
[02/03/2020 10:04:50.355600] 0
[02/03/2020 10:04:51.028900] 1
------------------------------
[02/03/2020 10:38:13.468200] 6

Как этого добиться простым l oop в bash скрипте? До сих пор я выяснил, как форматировать и изменять дату из строки NEW_VALUE1="$(date -d "$VALUE 2 seconds" +'%d/%m/%Y %H:%M:%S')", но безуспешно реализовать ее до функционального результата.

Ответы [ 3 ]

4 голосов
/ 03 марта 2020

С GNU awk:

awk -F'[[/:. ]' '
  { t=mktime($4" "$3" "$2" "$5" "$6" "$7) }
  NR>1 && t>tlast+2 { print "------------------------------" }; 1
  { tlast=t }
' file
  • Использование [, /, : . и пробела в качестве символов-разделителей полей и создание отметки времени t для каждой строки.
  • Вывести разделительную строку, если это не первая строка, и если t > tlast + 2.
  • Распечатать текущую строку.
  • Назначить значение t до tlast.
1 голос
/ 03 марта 2020

Убедите себя в следующем (или укажите мне, почему я не прав):


Учитывая две последовательные строки, вторая (назовите ее y) принадлежит той же части первой (назовите это x), если они оба совпадают до последнего : и

  • Если s(x) является четным, то s(y) лежит в интервале [s(x), s(x)+1].
  • Если s(x) нечетно, то s(y) лежит в интервале [s(x)-1, s(x)].

, где s(x) - это число секунд в строке x. Например, для верхней строки предусмотрено s(x)=58. Следующая строка должна быть в том же разделе, потому что строка одинакова до последнего двоеточия и s(y)=58 ∈ [58,59]


Тогда у вас есть скрипт awk:

awk -F: '
    !((int($3)==i1 || int($3)==i2) && min==$2 && datehour==$1) {print "----";}
    {
        sec=int($3)
        min=$2
        datehour=$1
        if (sec % 2 == 0) {i1=sec;i2=sec+1}
        else {i1=sec-1;i2=sec}
        print
    }
' logfile
0 голосов
/ 03 марта 2020

Во-первых, если у вас GNU awk или mawk, используйте решение awk с mktime, это будет на намного быстрее, чем зацикливание в скрипте bash. Однако вы запросили решение bash, и это нормально, если вы имеете дело с менее чем тысячей строк или около того.

Способ упрощения добавления разделителей состоит в преобразовании даты в секунды, так как эпоха. Затем, чтобы проверить, нужен ли разделитель, достаточно просто добавить 2 к последней отметке даты. Если не первая строка, выведите разделитель и обновите текущие секунды до секунд с начала эпохи. Выводить строку, прочитанную из файла, каждую итерацию независимо от этого.

Вы можете написать это довольно просто, читая каждую строку из файла с помощью read и затем используя расширения параметра для удаления подстроки для обрезки. справа ']' до конца и слева до '[', оставляя только дату, которую можно использовать с date -d, как вы пытались. Вы можете сделать что-то похожее на:

secs=0      # initialize seconds zero

while read -r line; do              # read each line in log
    dstr="${line%]*}"               # trim from right through ']'
    dstr="${dstr#*[}"               # trim from left through '['
    epoch=$(date -d "$dstr" +%s)    # get seconds from epoch from date
    if (((epoch-secs) > 2)); then   # if current date 2 greater than secs
        # if not first line, output the separator
        ((secs > 0)) && printf -- "------------------------------\n"
        secs="$epoch"               # update secs to epoch
    fi
    echo "$line"                    # output each line
done < file

Пример использования / вывода

При вводе в file вы получите:

[02/03/2020 07:53:58.859000] 5
[02/03/2020 07:53:58.935300] 2
------------------------------
[02/03/2020 10:04:50.355600] 0
[02/03/2020 10:04:51.028900] 1
------------------------------
[02/03/2020 10:38:13.468200] 6

Хотя это делается относительно просто с date -d и сравнениями, для больших журналов awk (если у вас GNU awk или mawk), то использование mktime будет на порядка быстрее, чем решение сценария оболочки.

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