Pergunta

Estou tentando escrever um script de análise de log para extrair eventos com falha. Eu posso puxá -las com grep:

$ grep -A5 "FAILED" log.txt

2008-08-19 17:50:07 [7052] [14] DEBUG:      data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 33   :FAILED  err:023
2008-08-19 17:50:07 [7052] [14] DEBUG:      data: 20 74 65 78 74 3a 20 00                            text: .
2008-08-19 17:50:07 [7052] [14] DEBUG:    Octet string dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [14] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1158667543, dst=447872123456, type=2
--
2008-08-19 17:50:07 [7052] [8] DEBUG:      data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 34   :FAILED  err:024
2008-08-19 17:50:07 [7052] [8] DEBUG:      data: 20 74 65 78 74 3a 20 00                            text: .
2008-08-19 17:50:07 [7052] [8] DEBUG:    Octet string dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [8] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1040097716, dst=447872987654, type=2

O que estou interessado é, para cada bloco, o código de erro (ou seja, o "023" parte de ": falha err: 023" na primeira linha) e o número do DST (ou seja, "447872123456" de "dst = 447872123456" na última linha.)

Alguém pode ajudar com uma lineadora para extrair esses dois valores ou fornecer algumas dicas sobre como devo abordar isso?

Foi útil?

Solução

grep -A 5 FAILED log.txt | \              # Get FAILED and dst and other lines
    egrep '(FAILED|dst=)' | \             # Just the FAILED/dst lines
    egrep -o "err:[0-9]*|dst=[0-9]*" | \  # Just the err: and dst= phrases
    cut -d':' -f 2 | \                    # Strip "err:" from err: lines
    cut -d '=' -f 2 | \                   # Strip "dst=" from dst= lines
    xargs -n 2                            # Combine pairs of numbers

023 447872123456
024 447872987654

Como em todos os lineadores de "um" da Shell, há quase certamente uma maneira mais elegante de fazer isso. No entanto, acho a abordagem iterativa muito bem -sucedida para obter o que quero: comece com muita informação (seu grep), depois restrinja as linhas que eu quero (com grep) e depois retire as partes de cada linha que eu quero (com com cortar).

Enquanto o uso da caixa de ferramentas Linux leva mais linhas, você só precisa conhecer o básico de alguns comandos para fazer o que quiser. Uma alternativa é usar idiomas AWK, Python ou de script, que requerem conhecimento de programação mais especializado, mas terá menos espaço na tela.

Outras dicas

Uma solução simples em Ruby, aqui está filter.rb:

#! /usr/bin/env ruby
File.read(ARGV.first).scan(/:FAILED\s+err:(\d+).*?, dst=(\d+),/m).each do |err, dst|
  puts "#{err} #{dst}"
end

Execute -o com:

ruby filter.rb my_log_file.txt

E você recebe:

023 447872123456
024 447872987654

Se sempre houver o mesmo número de campos, você poderia apenas

grep -A5 "FAILED" log.txt | awk '$24~/err/ {print $24} $12~/dst/{print $12}' error.txt

err:023
dst=447872123456,
err:024
dst=447872987654,

E, dependendo da aparência do restante do arquivo, você poderá pular o Grep All Togther.

O "$ 24 ~/ err/ {print $ 24}"A parte diz ao AWK para imprimir o número 24 do campo se contiver err, ~/ xxx/ onde xxx é uma expressão regular.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top