Como buscar 3 linhas acima de um parâmetro correspondente

0

Eu quero imprimir 3 linhas acima de um parâmetro correspondente em um arquivo de log. Eu estou usando o seguinte comando, mas isso me dá um erro. Existe alguma alternativa para isso.

grep -A 3 "exception" Services.log

Ocorre o seguinte erro:

grep: Not a recognized flag: A
Usage: grep [-r] [-R] [-H] [-L] [-E|-F] [-c|-l|-q] [-insvxbhwyu] [-p[parasep]] -e pattern_list...
        [-f pattern_file...] [file...]
    
por Hamas Rizwan 05.08.2018 / 12:28

2 respostas

2

O comando awk a seguir fornece a linha que contém a string exception junto com três linhas de "before context" ( -B 3 com GNU grep e algumas outras grep implementations):

awk 'BEGIN { bc=3 } { lines[NR%(bc+1)] = $0 } /exception/ { for (i=1; i<=(bc+1); ++i) print lines[(NR+i)%(bc+1)] }' file

Isso mantém um "buffer circular", lines , de bc+1 lines, em que bc é o número de linhas de "before context" que você deseja. Quando uma linha corresponde ao padrão exception , o conteúdo desse buffer é impresso.

Isso não manipula adequadamente o caso em que ocorre uma correspondência dentro de o "contexto anterior" de outra correspondência, ou onde a primeira correspondência no arquivo ocorre com menos de bc linhas no arquivo.

Generalizado em um script que fornece uma quantidade configurável de contexto antes e depois para algum padrão:

#!/bin/sh

# Usage:
#    ./script [ -A n ] [ -B n ] PATTERN FILE ...

after=0
before=0

while getopts 'A:B:' opt; do
    case $opt in
    A)
        after=$OPTARG
        ;;
    B)
        before=$OPTARG
        ;;
    *)
        echo 'error in command line parsing' >&2
        exit 1
    esac
done
shift "$(( OPTIND - 1 ))"

pattern=$1
shift

pattern=$pattern awk -v bc="$before" -v ac="$after" '
    { lines[NR%(bc+1)] = $0 }
    $0 ~ ENVIRON["pattern"] {
        for (i=1; i<=(bc+1); ++i) print lines[(NR+i)%(bc+1)]
        print_after=ac
        next
    }
    print_after > 0 { print; print_after-- }' "$@"

Teste:

$ cat file
1
2
3
4
5
exception
6
7
8
9
0
exception
$ sh script.sh -B 3 exception file
3
4
5
exception
8
9
0
exception
$ sh script.sh -A 3 exception file
exception
6
7
8
exception
$ sh script.sh -A 1 -B 1 exception file
5
exception
6
0
exception
    
por 05.08.2018 / 13:26
0

Simples, mas não necessariamente eficiente:

tac Services.log | awk '/exception/ {L = NR + 4} NR < L' | tac
    
por 05.08.2018 / 12:44

Tags