2008-10-30 3 views
0

Я пытаюсь написать скрипт синтаксического анализа журнала для извлечения неудачных событий. Я могу вытащить их с 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 

То, что я заинтересован в том, для каждого блока, код ошибки (т.е. «023» часть «: FAILED ERR: 023» на первой линии) и dst number (т.е. «447872123456» от «dst = 447872123456» на последней строке.)

Может ли кто-нибудь помочь с одним слоем оболочки, чтобы извлечь эти два значения, или дать некоторые подсказки относительно того, как я должен подходить к этому ?

ответ

2
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 

Как и для всех оболочек «одного» -линера, существует почти наверняка более элегантный способ сделать это. Тем не менее, я считаю, что итеративный подход очень успешный для получения того, что я хочу: начните с слишком большой информации (ваш grep), затем сузите строки, которые я хочу (с grep), а затем вырежьте части каждой строки, которую я хочу (с порез).

При использовании набора инструментов linux требуется больше строк, вам нужно знать только основы нескольких команд, чтобы делать что угодно. Альтернативой является использование awk, python или других языков сценариев, которые требуют более специализированных знаний в области программирования, но будут занимать меньше места на экране.

+0

Помните, что используемая команда grep не является стандартной - она ​​использует функцию GNU-only -A 5; Аналогично, опция egrep -o не является стандартной. Это предупреждение - не большая проблема (если вы не используете GNU grep/egrep). –

0

Простое решение в Ruby, здесь 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 

Выполнить его:

ruby filter.rb my_log_file.txt 

И вы получите:

023 447872123456 
024 447872987654 
0

Если есть всегда одинаковое количество полей вы могли бы просто

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

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

И в зависимости от того, как выглядит остальная часть файла, вы можете пропустить grep all togther.

«$ 24 ~/err/{print $ 24}« часть рассказывает awk, чтобы напечатать поле номер 24, если оно содержит err, ~/XXX/где XXX является регулярным выражением.

 Смежные вопросы

  • Нет связанных вопросов^_^