comando para extrair dados entre 2 linhas

comando para extrair dados entre 2 linhas

Tenho que extrair a exceção e o rastreamento de pilha correspondente a partir de um número de linha em um arquivo de log. Eu conheço a linha de partida, não do erro. como posso descobrir onde o rastreamento de pilha terminará no exemplo abaixo? Agradeço sua ajuda

exemplo
-------
07-10-2016 15:49:07.537 ERRO Alguma exceção
 linha 1 do stacktrace
 linha 2 do stacktrace
 .
 .
 linha stacktrace f
07-10-2016 15:49:07.539 depurar blá blá blá
07-10-2016 15:49:07.540 depurar blá blá blá

Responder1

Para resumir, você deseja imprimir linhas começando com o número da linha especificado e continuando até pouco antes da primeira linha seguinte que começa com uma data. No seu exemplo, a linha inicial é 3. Nesse caso:

$ 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

O código acima funciona da seguinte maneira:

  • if (NR==3)f=1

    No número da linha que você especificar, defina a variável fcomo um.

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

    Em outras linhas, defina fcomo zero se a linha começar com 10 caracteres que sejam dígitos ou travessões seguidos de um espaço. Em outras palavras, defina fcomo zero a primeira linha que começa com algo que se parece com uma data.

    Se necessário, podemos usar regexes mais complexas para identificar o início de uma data. Por exemplo, o seguinte requer que a linha comece com algo que se pareça com um dado, seguido por um espaço, seguido por algo que se pareça com tempo, seguido por uma vírgula.

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

    Ainda são possíveis melhorias adicionais neste aspecto.

  • f{print}

    Se ffor diferente de zero, imprima a linha.

    Para resumir, poderíamos substituir f{print}por apenas f. Isto é possível porque, quando uma ação não é especificada explicitamente, a ação padrão de printé usada.

Alternativa

Algumas versões do awk não suportam fatores de repetição como {10}. Se for esse o caso no seu sistema, tente:

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

Responder2

Supondo que todas as linhas de rastreamento de pilha comecem com um espaço em branco (espaço/tabulação), você pode combiná-las ( [[:blank:]]) no início da linha ( ^):

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

Responder3

Se o rastreamento que você deseja extrair começa na linha 2 de trace.loge seu final é indicado por uma linha que começa com uma data no formato AAAA-MM-DD (e não existem tais linhas com o rastreamento), então

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

imprimirá todas as linhas da linha 2atravéslinhan+3 (a primeira linha após o traço que começa com uma data). Como você não deseja a última linha, canalize o texto acima em um comando que remova a última linha:

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

ou

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

Se você precisar procurar uma datae um tempoe procure por

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

informação relacionada