Domanda

Sto cercando di scrivere uno script di analisi del registro per estrarre eventi non riusciti. Posso estrarli 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

Ciò che mi interessa è, per ogni blocco, il codice di errore (ovvero la parte "023" di "errore FAILED: 023" sulla prima riga) e il numero dst (ovvero "447872123456") da " dst = 447872123456 " nell'ultima riga.)

Qualcuno può aiutare con una shell one-liner a estrarre quei due valori o fornire alcuni suggerimenti su come dovrei affrontarlo?

È stato utile?

Soluzione

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

Come per tutte le shell "one", esiste quasi sicuramente un modo più elegante per farlo. Tuttavia, trovo che l'approccio iterativo abbia molto successo per ottenere ciò che voglio: iniziare con troppe informazioni (il tuo grep), quindi restringere le linee che voglio (con grep), quindi tagliare le parti di ogni linea che voglio (con tagliare).

Mentre l'utilizzo della toolbox di linux richiede più righe, devi solo conoscere le basi di alcuni comandi per fare praticamente tutto quello che vuoi. Un'alternativa è usare awk, python o altri linguaggi di scripting, che richiedono conoscenze di programmazione più specializzate ma occuperanno meno spazio sullo schermo.

Altri suggerimenti

Una soluzione semplice in Ruby, ecco 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

Eseguilo con:

ruby filter.rb my_log_file.txt

E ottieni:

023 447872123456
024 447872987654

Se c'è sempre lo stesso numero di campi, puoi semplicemente

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 a seconda dell'aspetto del resto del file potresti essere in grado di saltare il grep insieme.

Il " $ 24 ~ / err / {print $ 24} " parte dice a awk di stampare il campo numero 24 se contiene err, ~ / XXX / dove XXX è un'espressione regolare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top