蛮力方法涉及通过将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 XABCXXXQQQQXX | perl -pe 's/^(.*)X/$1Y/'
XABCXXXQQQQXY
注意^ 是多余的,因为regular-expression quantifiers 是贪婪的,但我喜欢用它来强调。
将此技术应用于您的问题,您可以在配置文件中搜索包含错误的最后一行,如以下程序中所示:
#! /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 switch (“multi-line”),^ 匹配逻辑行边界。
到目前为止,我们已经知道了模式
/\A.* ^ .../
匹配最后一行看起来像的东西。 negative look-ahead assertion (?!...) 查找不是合法配置行的行。通常. 匹配除换行符以外的任何字符,但/s switch (“single line”) 解除了此限制。指定[^\r\n]+,即一个或多个既不是回车也不是换行的字符,不允许匹配溢出到下一行。
Look-around assertions 不捕获,所以我们用(.+?)$ 抓住违规行。在这种情况下使用. 是安全的原因是因为我们知道当前行是错误的并且non-greedy quantifier +? 会尽快停止匹配,在这种情况下是当前逻辑行的结尾。
所有这些正则表达式都使用/x switch (“extended mode”) 来允许额外的空格:目的是提高可读性。