
Мне нужно извлечь исключение и соответствующую трассировку стека, начиная с номера строки в файле журнала. Я знаю начальный номер строки ошибки. Как узнать, где закончится трассировка стека из приведенного ниже примера? Ценю вашу помощь
пример ------- 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}