Почему я получаю только один матч? - PullRequest
2 голосов
/ 08 сентября 2011

Я анализирую файл журнала, пытаясь вытащить строки, где фраза «failures =» является уникальной ненулевой цифрой.

Первая часть моего perl one liner вытянет все строкигде «сбои» больше нуля.Но эта часть файла журнала повторяется до тех пор, пока не произойдет новый сбой, т. Е. После первого сбоя записи журнала будут «failures = 1», до второй ошибки, после чего будет прочитано «failures = 2».

То, что я хотел бы сделать, это потянуть только первую строку, где это значение изменяется, и я подумал, что у меня это с этим:

cat -n Logstats.out | perl -nle 'print "Line No. $1: failures=$2; eventDelta=$3; tracking_id=$4" if /\s(\d+)\t.*failures=(\d+).*eventDelta=(.\d+).*tracking_id="(\d+)"/ && $2 > 0' | perl -ne 'print unless $a{/failures=\d+/}++'

Однако, это тянет только первую ненулевую строку «ошибка»и ничего больше.Что мне нужно изменить, чтобы он вытягивал все уникальные значения для «сбоев»?

заранее спасибо!

Обновление: количество текста в каждой строке до «tracking_id»больше текста, чем я могу опубликовать.Извините!

2011-09-06 14:14:18 [INFO] [logStats]: имя = имя-идентификатора = d6e6f4f0-4c0d-93b6-7a71-8e3100000030 successses = 1 сбоев = 0 пропущено =0 eventDelta = 41 оригинал = 188 смоделировано = 229 totalDelta = 41 AverageDelta = 41 мин = 0 max = 41 среднееOriginalDuration = 188 СреднееSimulatedDuriation = 229 (txid = b3036eca-6288-48ef-166f-5ae200000646 дата = 2011-09-02 08:00: 00 type = XML xml =

Ответы [ 3 ]

2 голосов
/ 08 сентября 2011
perl -ne 'print unless $a{/failures=\d+/}++'

не работает, так как хеш-индекс оценивается в скалярном контексте, а оператор m// не возвращает совпадение в скалярном контексте.Вместо этого он возвращает 1. Итак (поскольку каждая строка соответствует), то, что вы написали, эквивалентно:

perl -ne 'print unless $a{1}++'

, и я думаю, что вы можете увидеть проблему там.

Есть рядспособы обойти это, но я бы использовал:

perl -ne 'print unless /(failures=\d+)/ and $a{$1}++'

Однако я бы сделал все это за один вызов perl, включая нумерацию строк:

perl -nle '
   print "Line No. $.: failures=$1; eventDelta=$2; tracking_id=$3"
      if /failures=(\d+).*?eventDelta=(.\d+).*?tracking_id="(\d+)"/
      && $1 > 0
      && !$seen{$1}++
' Logstats.out

($. автоматически считает входные строки в Perl. При желании разрывы строк могут быть удалены, но на самом деле все будет работать как есть.)

1 голос
/ 08 сентября 2011

Поскольку ваш ввод не соответствует вашему регулярному выражению, я не могу вам помочь. Но я могу вам сказать, что при этом выполняется лот возврата - и это плохо, если после той части, которая вас интересует, много данных.

Итак, вот несколько альтернативных идей:

qr{ \s                    # a single space
    failures=(\d+)        # the entry for failures
    \s+                   # at least one space
    skipped=\d+           # skipped 
    \s+ 
    eventDelta=(.\d+)     
    .*?                   # any number of non-newline characters *UNTIL* ...
    \btracking_id="(\d+)" # another specified sequence of data
  }x;
  • Парсер будет сканировать «skipped =», а затем группу цифр намного быстрее, чем сканирование остальной части строки и обратного отслеживания, когда он возвращается к «eventDelta =», лучше поместить его, если вы знаете , он всегда будет там.

  • Поскольку вы не указали tracking_id в своем примере, я не могу сказать, как это происходит, поэтому в этом случае мы использовали не жадный любое совпадение, которое всегда будет ищу следующую последовательность. Опять же, если в строке много данных, вы не хотите сканировать, а затем завершать и возвращаться назад, пока не обнаружите, что уже прочитали 'tracking_id = "nnn"'. Однако, оглядываясь на время обработки, все же лучше указать «skipped =» и все возможные значения, а не жадное «любое совпадение».

  • Вы также заметите, что после принятия любых данных я указываю, что tracking_id должен отображаться на границе слова, что устраняет неоднозначность его значения из возможных - хотя вряд ли 'backtracking_id ='.

1 голос
/ 08 сентября 2011

вы можете использовать хеш для хранения результатов и распечатать его:

perl -nle '$f{$2} ||= "Line No. $1: failures=$2; eventDelta=$3; tracking_id=$4" if /\s(\d+)\t.*failures=(\d+).*eventDelta=(.\d+     ).*tracking_id="(\d+)"/ && $2;END{ print $f{$_} for keys %f }' Logstats.out

(не проверено из-за отсутствия входных данных ...)

НТН, Пол

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...