Pregunta

Estoy intentando escribir un script de análisis de registro para extraer eventos fallidos. Puedo sacar estos con 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

Lo que me interesa es, para cada bloque, el código de error (es decir, la parte " 023 " de: quot; ERROR err: 023 en la primera línea) y el número dst (es decir, " 447872123456 " de " dst = 447872123456 " en la última línea.)

¿Alguien puede ayudar con un shell de una sola línea para extraer esos dos valores o proporcionar algunas sugerencias sobre cómo debo abordar esto?

¿Fue útil?

Solución

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

Al igual que con todas las carcasas de shell "uno", existe una forma más elegante de hacerlo. Sin embargo, encuentro que el enfoque iterativo es muy exitoso para obtener lo que quiero: comenzar con demasiada información (su grep), luego reducir las líneas que quiero (con grep), luego cortar las partes de cada línea que quiero (con corte).

Mientras que usar la caja de herramientas de Linux toma más líneas, solo tienes que conocer los conceptos básicos de algunos comandos para hacer lo que quieras. Una alternativa es utilizar awk, python u otros lenguajes de scripting, que requieren conocimientos de programación más especializados pero que ocuparán menos espacio en la pantalla.

Otros consejos

Una solución simple en Ruby, aquí 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

Ejecutalo con:

ruby filter.rb my_log_file.txt

Y obtienes:

023 447872123456
024 447872987654

Si siempre hay la misma cantidad de campos, simplemente

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

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

Y dependiendo de cómo se vea el resto del archivo, es posible que puedas omitir el grep todos juntos.

El " $ 24 ~ / err / {print $ 24} " la parte le dice a awk que imprima el campo número 24 si contiene un error, ~ / XXX / donde XXX es una expresión regular.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top