Подход методом перебора подразумевает настройку собственного конвейера, указав 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
(«расширенный режим») , чтобы обеспечить дополнительный пробел: цель состоит в том, чтобы улучшить читаемость.