Необходимо напечатать последнее вхождение строки в Perl - PullRequest
0 голосов
/ 12 августа 2010

У меня есть скрипт на Perl, который ищет ошибку в конфигурационном файле, но он распечатывает любое возникновение ошибки.Мне нужно сопоставить то, что находится в файле конфигурации, и распечатать только в последний раз, когда произошла ошибка.Есть идеи?


Ух ты ... Я не ожидал такой большой реакции.Я должен был быть более ясным, заявив, что это для мониторинга журналов в окне Windows, которое отправляет предупреждение в Nagios.На самом деле это моя первая программа на Perl, и вся эта информация была очень полезной.Кто-нибудь знает, как я могу применить это любой из хвостовых ответов на коробке wintel?

Ответы [ 4 ]

4 голосов
/ 12 августа 2010

Еще один способ сделать это:

perl -n -e '$e = $1 if /(REGEX_HERE)/;  END{ print $e }' CONFIG_FILE_HERE
4 голосов
/ 12 августа 2010

Что именно вам нужно напечатать? Строка, содержащая ошибку? Больше контекста, чем это? File::ReadBackwards может быть полезным.

3 голосов
/ 12 августа 2010

В общих чертах:

my $errinfo;
while (<>)
{
    $errinfo = "whatever" if (m/the error pattern/);
}
print "error: $errinfo\n" if ($errinfo);

Это ловит все ошибки, но не печатает до конца, когда выживает только последняя.

0 голосов
/ 12 августа 2010

Подход методом перебора подразумевает настройку собственного конвейера, указав STDOUT на tail. Это позволяет вам распечатать все ошибки, а затем до 10000 * беспокоиться только о выпуске последней.

Вы не указали, поэтому я предполагаю, что допустимая строка конфигурации имеет вид

Name = some value

Совпадение, которое является простым:

  • ^ (начиная с начала строки)
  • \w+ (один или несколько «символов слова»)
  • \s+ (с последующим обязательным пробелом)
  • = (сопровождается знаком равенства)
  • \s+ (более обязательный пробел)
  • .+ (некоторые обязательные значения)
  • $ (окончание в конце строки)

Склеив это, мы получим

#! /usr/bin/perl

use warnings;
use strict;

# for demo only
*ARGV = *DATA;

my $pid = open STDOUT, "|-", "tail", "-1" or die "$0: open: $!";
while (<>) {
  print unless /^ \w+ \s+ = \s+ .+ $/x;
}

close STDOUT or warn "$0: close: $!";

__DATA__
This = assignment is ok
But := not this
And == definitely not this

Выход:

$ ./lasterr 
And == definitely not this

При использовании регулярных выражений, если вы хотите, чтобы в последний раз был шаблон, поместите ^.* в начало шаблона. Например, чтобы заменить последний X на входе на Y, используйте

$ echo XABCXXXQQQXX | perl -pe 's/^(.*)X/$1Y/'
XABCXXXQQQXY

Обратите внимание, что ^ является избыточным, потому что квантификаторы регулярных выражений являются жадными, но мне нравится иметь его там для выделения.

Применяя этот метод к вашей проблеме, вы можете искать последнюю строку в вашем конфигурационном файле, которая содержит ошибку, как в следующей программе:

#! /usr/bin/perl

use warnings;
use strict;

local $_ = do { local $/; scalar <DATA> };
if (/\A.* ^(?! \w+ \s+ = \s+ [^\r\n]+ $) (.+?)$/smx) {
  print $1, "\n";
}

__DATA__
This = assignment is ok
But := not this
And == definitely not this

Синтаксис регулярного выражения немного отличается, потому что $_ содержит несколько строк, но принцип тот же. \A аналогично ^, но соответствует только в начале строки для поиска. С переключателем /m («многострочный») , ^ совпадают на границах логической линии.

До этого момента мы знаем схему

/\A.* ^ .../

соответствует последней строке, которая выглядит как-то. отрицательное прогнозное утверждение (?!...) ищет строку, которая не допустимая строка конфигурации. Обычно . соответствует любому символу, кроме новой строки, но переключатель /s («одиночная строка») снимает это ограничение. Указание [^\r\n]+, то есть один или несколько символов, которые не являются ни переводом каретки, ни переводом строки, не позволяет совпадению перетекать в следующую строку.

Подтверждающие утверждения не фиксируются, поэтому мы берем неправильную строку с (.+?)$. Причина, по которой безопасно использовать . в этом контексте, заключается в том, что мы знаем, что текущая строка неверна, и негладкий квантификатор 1087 * прекращает сопоставление, как только может, что в данном случае конец текущей логической строки.

Все эти регулярные выражения используют переключатель /x («расширенный режим») , чтобы обеспечить дополнительный пробел: цель состоит в том, чтобы улучшить читаемость.

...