Сценарий оболочки / регулярное выражение: извлечение через несколько строк

StackOverflow https://stackoverflow.com/questions/250717

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Простое решение в 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

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

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 вместе.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top