Imprima uma linha apenas se a próxima linha NÃO contiver uma correspondência específica

12

Estou tentando pesquisar um arquivo de log para atividades registradas que não foram concluídas. Por exemplo, eu registro uma "Iniciando a atividade para o ID 1234 ..." e, se obtiver êxito, a próxima linha será "Atividade 1234 concluída".

Estou tentando obter as linhas "Iniciando ..." que NÃO são seguidas pelas linhas "Concluídas" correspondentes.

Exemplo de arquivo de log

Starting activity for ID 1234
ID 1234 completed successfully
Starting activity for ID 3423
ID 3423 completed successfully
Starting activity for ID 9876
ID 9876 completed successfully
Starting activity for ID 99889
ID 99889 completed successfully
Starting activity for ID 10011
ID 10011 completed successfully
Starting activity for ID 33367
Starting activity for ID 936819
ID 936819 completed successfully

Neste exemplo, eu estaria procurando a saída para ser:

Starting activity for ID 33367

... porque não é seguido por uma linha "concluída".

Eu tentei fazer isso com grep e awk , mas não obtive muito sucesso. Estou assumindo que isso pode ser feito com uma dessas ferramentas, mas meus grep e awk chops não são avançados.

Procurando um padrão grep ou awk rápido e confiável para fornecer os resultados que preciso aqui.

    
por PattMauler 30.07.2012 / 16:22

4 respostas

10

Aqui está uma alternativa awk :

awk '
  /^Starting/ { I[$5] = $0                  }
  /^ID/       { delete I[$2]                }
  END         { for (key in I) print I[key] }
' infile

Saída:

Starting activity for ID 33367

A matriz I associativa rastreia quais IDs foram vistos.

    
por 30.07.2012 / 17:11
2

Veja como você pode fazer isso com o GNU sed:

sed -r 'N; /([0-9]+)\n\w+\s+/d; P; D' infile
  • N lê mais uma linha no espaço padrão.
  • A regex de correspondência verifica se IDs idênticos são encontrados, se o espaço de padrão for excluído ( d ) e o ciclo for reiniciado.
  • Se não corresponder, imprima a primeira linha no espaço padrão ( P ) e exclua-a ( D ).
por 21.03.2013 / 09:08
2
sed '$!N;/\n.*completed/d;P;D' <input

Isso excluirá da saída todas as linhas de entrada que não forem seguidas por uma linha que corresponda à string concluída .

    
por 10.12.2016 / 15:27
1

se a sua instalação suportar o pcregrep, a opção multilinha (-M) será útil.

pcregrep -M -o '\AStarting activity for ID (\d+)\n(?!ID )' t.z

Iniciando a atividade para o ID 33367

    
por 30.07.2012 / 17:02

Tags