Необходимо напечатать последнее вхождение строки в Perl
У меня есть скрипт на Perl, который ищет ошибку, которая находится в файле конфигурации, но он распечатывает любое возникновение ошибки. Мне нужно сопоставить то, что находится в файле конфигурации, и распечатать только в последний раз, когда произошла ошибка. Есть идеи?
Ух ты... Я не ожидал такой большой реакции. Я должен был быть более ясным, заявив, что это для мониторинга журналов в окне Windows, которое отправляет предупреждение в Nagios. На самом деле это моя первая программа на Perl, и вся эта информация была очень полезной. Кто-нибудь знает, как я могу применить это любой из хвостовых ответов на коробке wintel?
4 ответа
Еще один способ сделать это:
perl -n -e '$e = $1 if /(REGEX_HERE)/; END{ print $e }' CONFIG_FILE_HERE
Что именно вам нужно напечатать? Строка, содержащая ошибку? Больше контекста, чем это? File::ReadBackwards
может быть полезным
В общих чертах:
my $errinfo;
while (<>)
{
$errinfo = "whatever" if (m/the error pattern/);
}
print "error: $errinfo\n" if ($errinfo);
Это ловит все ошибки, но не печатает до конца, когда выживает только последняя.
Подход грубой силы включает в себя настройку собственного конвейера, указывая STDOUT
в tail
, Это позволяет распечатать все ошибки, а затем до tail
беспокоиться только о выпуске последнего.
Вы не указали, поэтому я предполагаю, что допустимая строка конфигурации имеет вид
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 И == определенно не это
С помощью регулярных выражений, когда вы хотите, чтобы последнее вхождение шаблона ^.*
в передней части вашего шаблона. Например, чтобы заменить последний 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]+
то есть, один или несколько символов, которые не являются ни переводом каретки, ни переводом строки, не позволяют совпадению перетекать в следующую строку.
Проверочные утверждения не фиксируются, поэтому мы берем оскорбительную строку с (.+?)$
, Причина, по которой это безопасно использовать .
в этом контексте, потому что мы знаем, что текущая строка плохая и не жадный квантификатор +?
прекращает сопоставление, как только может, что в данном случае является концом текущей логической строки.
Все эти регулярные выражения используют /x
Переключатель ("расширенный режим"), чтобы освободить лишние пробелы: цель - улучшить читаемость.