我在 Perl 中有一个脚本,用于搜索配置文件中的错误,但它会打印出任何出现的错误。我需要匹配配置文件中的内容并仅在上次发生错误时打印出来。有任何想法吗?
哇...我没想到会有这么多回应。我应该更清楚地说明这是用于向 Nagios 发送警报的 Windows 框上的日志监控。这实际上是我的第一个 Perl 程序,所有这些信息都非常有帮助。有谁知道我如何在 wintel 盒子上应用这个任何尾部答案?
Another way to do it:
perl -n -e '$e = $1 if /(REGEX_HERE)/; END{ print $e }' CONFIG_FILE_HERE
What exactly do you need to print? The line containing the error? More context than that?
File::ReadBackwards
can be helpful.
概述:
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
输出:
$ ./laster 而且==绝对不是这个
使用正则表达式,当您想要模式的最后一次出现时,请将^.*
其放在模式的前面。例如,要将输入中的最后一个 X 替换为 Y,请使用
$ 回声 XABCXXXQQQQXX | perl -pe 's/^(.*)X/$1Y/' XABCXXXQQQQXY
请注意,这^
是多余的,因为正则表达式量词是贪婪的,但我喜欢把它放在那里以强调。
将此技术应用于您的问题,您可以在配置文件中搜索包含错误的最后一行,如以下程序中所示:
#! /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
开关 (“multi-line”),^
匹配逻辑行边界。
至此,我们知道了模式
/\A.* ^ .../
匹配看起来像某物的最后一行。否定的前瞻断言 (?!...)
查找不是合法配置行的行。通常.
匹配除换行符以外的任何字符,但/s
开关(“单行”)解除了这个限制。指定[^\r\n]+
,即一个或多个既不是回车也不是换行的字符,不允许匹配溢出到下一行。
环顾断言不会捕获,因此我们使用(.+?)$
. 在这种情况下使用它是安全的原因.
是因为我们知道当前行是错误的,并且非贪婪量词+?
会尽快停止匹配,在这种情况下是当前逻辑行的结尾。
所有这些正则表达式都使用/x
开关(“扩展模式”)来允许额外的空格:目的是提高可读性。