команда для извлечения данных между 2 строками

команда для извлечения данных между 2 строками

Мне нужно извлечь исключение и соответствующую трассировку стека, начиная с номера строки в файле журнала. Я знаю начальный номер строки ошибки. Как узнать, где закончится трассировка стека из приведенного ниже примера? Ценю вашу помощь

пример
-------
2016-10-07 15:49:07,537 ОШИБКА Некоторое исключение
 строка трассировки стека 1
 строка трассировки стека 2
 .
 .
 строка трассировки стека n
2016-10-07 15:49:07,539 отладка бла-бла-бла
2016-10-07 15:49:07,540 отладка бла-бла-бла

решение1

Подводя итог, вы хотите напечатать строки, начиная с указанного вами номера строки и продолжая до первой следующей строки, которая начинается с даты. В вашем примере начальная строка — 3. В этом случае:

$ awk '{if (NR==3)f=1; else if (/^[0-9-]{10} /)f=0} f{print}' trace.log
2016-10-07 15:49:07,537 ERROR Some exception
 stacktrace line 1
 stacktrace line 2
 .
 .
 stacktrace line n

Приведенный выше код работает следующим образом:

  • if (NR==3)f=1

    В строке с указанным номером установите переменную fна единицу.

  • else if (/^[0-9-]{10} /)f=0

    В других строках установите fноль, если строка начинается с 10 символов, которые являются цифрами или тире, за которыми следует пробел. Другими словами, установите fноль в первой строке, которая начинается с чего-то, похожего на дату.

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

    awk '{if (NR==3)f=1; else if (/^[0-9-]{10} [0-9:]{8},/)f=0} f{print}' trace.log
    

    Возможны и дальнейшие улучшения.

  • f{print}

    Если fненулевое значение, выведите строку.

    Для краткости мы могли бы заменить f{print}на просто . Это возможно, поскольку, когда действие не указано явно, используется fдействие по умолчанию .print

Альтернатива

Некоторые версии awk не поддерживают факторы повторения, такие как {10}. Если это так в вашей системе, попробуйте:

awk '{if (NR==3)f=1; else if (/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] /)f=0} f{print}' trace.log

решение2

Предполагая, что все строки трассировки стека начинаются с пробела (пробел/табуляция), вы можете сопоставить их ( [[:blank:]]) в начале строки ( ^):

grep '^[[:blank:]]' file.log

решение3

Если трасса, которую вы хотите извлечь, начинается на строке 2 из trace.log, а ее конец обозначен строкой, которая начинается с даты в формате ГГГГ-ММ-ДД (и таких строк в трассе нет), то

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log

выведет каждую строку, начиная со строки 2черезлиниян+3 (первая строка после трассировки, которая начинается с даты). Поскольку вам не нужна эта последняя строка, перенесите вышеизложенное в команду, которая удаляет последнюю строку:

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | head -n -1

или

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | sed '$d'

Если вам нужно найти датуи время, затем найдите

^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}

Связанный контент