我在Perl中有一个脚本,用于搜索配置文件中的错误,但它会打印出任何错误。我需要匹配配置文件中的内容,并仅在上次错误发生时打印出来。有什么想法吗?
答案 0 :(得分:4)
另一种方法:
perl -n -e '$e = $1 if /(REGEX_HERE)/; END{ print $e }' CONFIG_FILE_HERE
答案 1 :(得分:4)
您到底需要打印什么?包含错误的行?比那更多的背景?
File::ReadBackwards
可能会有所帮助。
答案 2 :(得分:3)
概述:
my $errinfo;
while (<>)
{
$errinfo = "whatever" if (m/the error pattern/);
}
print "error: $errinfo\n" if ($errinfo);
这会捕获所有错误,但直到最后才打印,只有最后一个存在。
答案 3 :(得分:0)
蛮力方法涉及通过将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 And == definitely not this
使用正则表达式,当您想要最后一次出现模式时,请将^.*
放在模式的前面。例如,要用Y替换输入中的最后一个X,请使用
$ echo XABCXXXQQQXX | perl -pe 's/^(.*)X/$1Y/' XABCXXXQQQXY
请注意,^
是多余的,因为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”)来允许额外的空格:目的是提高可读性。