Я хочу grep для блока журналов вокруг конкретного сообщения об ошибке. Скажем, я знаю, что мой журнал выглядит так:

[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)

Я заинтересован во всем этом блоке. Есть ли способ сосредоточить мой grep вокруг FATAL ошибки, и перейти к Started GET и до Completed 200 OK?

Я знаю, что grep -B 123 -A 456 "FATAL" file.txt поможет, но я должен заранее знать, как далеко FATAL от первой строки (123) и последней строки (456) [1].

[1] http://unixhelp.ed.ac.uk/CGI/man-cgi?grep

3 ответа3

0

Боюсь, что у grep такой возможности нет. Perl и / или Python может. Сверху головы (без особых размышлений) я придумал следующую awk-комбинацию.

 awk '/Started GET/{print ""};1' blurble | awk 'BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/FATAL/{print $0}'

Принимая во внимание фрагмент журнала, созданный из вашего фрагмента (x4), и несколько дополнительных строк "другого журнала" и две строки "FATAL" удалены, я печатаю два сегмента:

[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)

Запуск двух awk для файла (я назвал его размытым) дает такой вывод:

[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)

[----] I, [2014-04-10T19:12:36.294512 #1910:e93004]  INFO -- : Started GET "/ems_infra/new"  for 4.2.2.2 at 2014-04-10 15:12:36 -0400 
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs 
[----] F, [2014-04-10T19:12:36.346380 #1910:e93004] FATAL -- : Error caught: [NoMethodError] undefined method `invert' for nil:NilClass
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.345863 #1910:e93004]  INFO -- : other random logs
[----] I, [2014-04-10T19:12:36.369320 #1910:e93004]  INFO -- : Completed 200 OK in 69ms (Views: 22.5ms | ActiveRecord: 0.0ms)
0

вот один лайнер с использованием сед

sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log

один лайнер расширен для объяснения

# do not print lines unless explicitly told to do so
sed -n '

  # put everything between Started and Completed in hold space
  /Started/,/Completed/ H;

  # if at Completed
  /Completed/ {

    # empty the pattern space
    z;

    # switch hold space with pattern space
    x;

    # if FATAL in pattern space then print
    /FATAL/p

  }

' log

обратите внимание, что это напечатает пустую строку между каждым блоком. пустая строка происходит от z;x; комбо. z очищает пространство шаблона. x переключатели удерживают пробел с пробелом это означает, что после z;x; в трюме есть пустая строка. если вы не очистите пространство шаблона перед переключением с удержанием пространства, у вас будет последняя строка из предыдущего блока в следующем блоке. я попытался обойти это, чтобы предотвратить пустую строку, но это сделало код гораздо более запутанным.

если пустая строка сильно вас беспокоит, вы можете отфильтровать ее ... с помощью другой команды sed.

sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log | sed '/^$/d'

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

sed -n '/Started/,/Completed/H;/Completed/{z;x;/FATAL/p}' log | sed 's/^$/--/'

вот самое простое решение, которое я придумал, который покончил с пустой строкой

sed -n '

  # replace hold space with pattern space
  /Started/ h

  /Started/,/Completed/ {

    # skip the first line because it is already in hold space
    /Started/ n

    # append pattern space to hold space
    H
  }

  /Completed/ {

    # switch hold space with pattern space
    x

    # if FATAL in pattern space then print
    /FATAL/ p
  }

' log

так же, как обязательный один лайнер

sed -n '/Started/h;/Started/,/Completed/{/Started/n;H};/Completed/{x;/FATAL/p}' log
0

У меня есть скрипт, который может помочь: https://github.com/jakl/blocks

./blocks.pl --delim 'Запущено GET | Завершено 200 OK' --term 'FATAL'

Он разбивает ваш журнал на блоки, начинающиеся или заканчивающиеся на --delim, и печатает те, которые содержат --term

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .