Contagem de linhas que correspondem ao padrão e à linha anterior correspondente

5

Eu quero contar o número de vezes que uma função é excluída com sucesso. O problema é que uma linha do arquivo de log mostrará que o script está prestes a excluir a função:

Prepare to remove role X

A próxima linha me dirá se a exclusão foi bem-sucedida ou não:

Exclusão bem-sucedida:

Delete Successful

Exclusão sem sucesso:

Failed to delete role X: error code

Como faço para contar o número de exclusões de função bem-sucedidas? Eu usaria apenas o seguinte grep:

grep "Delete Successful" | wc -l

No entanto, também estou excluindo políticas registradas da mesma maneira que as funções acima. IE:

Prepare to delete policy X
Delete Successful

OR

Failed to delete policy X: error code

Qualquer forma de procurar por "Prepare to delete role" em uma linha e depois contar o número de vezes que a linha seguinte diz "delete successful?"

    
por user33814 08.03.2013 / 14:39

4 respostas

6

Se o seu grep é o GNU grep , aqui está uma solução rápida e suja:

grep -A1 "Prepare to remove role" | grep "Delete Successful" | wc -l

A opção grep -A1 diz ao grep para imprimir a linha correspondente E uma linha seguindo a linha correspondente. O segundo grep, em seguida, imprime apenas as linhas em que a exclusão é bem-sucedida.

Observe que isso só funcionará de forma confiável quando a linha "Preparar para remover a função X" for sempre seguida imediatamente pela linha "Excluir bem-sucedida".

Observe também que você não precisa de wc -l porque o grep tem essa funcionalidade incorporada:

grep -A1 "Prepare to remove role" | grep -c "Delete Successful"
    
por 08.03.2013 / 14:52
3

com o awk:

awk '/Delete Successful/ && last_line ~ /Prepare to remove role/ {n++}
     {last_line=$0}
     END {print n+0}'
    
por 08.03.2013 / 15:23
1

Assumindo que essas são as únicas duas maneiras em que "Delete Successful" pode entrar no log, por que não usar um pouco de matemática?

SUCCESS=$(grep 'Delete Successful' | wc -l)
POLICY_COUNT=$(grep 'Prepare to delete policy X' | wc -l)
POLICY_FAIL=$(grep 'Failed to delete policy X' | wc -l)
POLICY_SUCCESS=$(( $POLICY_COUNT - $POLICY_FAIL ))
ROLE_SUCCESS=$(( $SUCCESS - $POLICY_SUCCESS ))
    
por 08.03.2013 / 20:54
0

(Como os algoritmos somente de shell se mostraram muito mais lentos do que as ferramentas externas, eu simplesmente removi todas as referências a eles. Os dados do benchmark podem ser interessantes.)

Dados de teste:

Prepare to remove role foo
Delete Successful
Prepare to remove role bar
Failed to delete role bar: 1
Prepare to remove policy baz
Delete Successful
Prepare to remove role ban
Delete Successful
something
else
Prepare to remove role bay
Failed to delete role bar: 2
Prepare to remove role bat
Failed to delete role bar: 1

Referência com os dados de teste repetidos em milhões vezes (ou seja, 306 MB), melhor de três execuções intercaladas, classificadas aumentando real time:

Código de teste:

for index in {1..3}
do
    for path in grep.sh awk.sh
    do
        echo "$path:"
        time bash "$path"
        echo
    done
done

Sistema de teste: Intel Core i7 @ 3,07 GHz com 6 GB de RAM.

    
por 08.03.2013 / 19:57