这是条目的样子:
Jan 26 20:53:31 hostname logger: System rebooted for hard disk upgrade
我正在编写一个小应用程序来解析这样的条目,并通过电子邮件将格式正确的消息发送给管理员。我正在用Perl编写并找到了split()函数,这正是我正在寻找的:
my @tmp = split(/ /, $string, 4);
@tmp = {$date, $hostname, $facility, $message)
这就是我希望得到的。 Split()可以处理$ message部分中的空格,因为我限制了要分割的“单词”数量。但是,$ date部分中的空格将其抛弃。有没有一种干净的方法可以让这些变量代表它们应该是什么?
我知道我可以使用substr()来获取前15个字符(日期),然后使用split()并将其限制为3个单词而不是4个单词,然后从那里获取所有字符串。但有更优雅的方式来做到这一点吗?
答案 0 :(得分:4)
如果单行内容对于优雅很重要,请分隔不带数字的空格:
my ( $time, $hostname, $facility, $message ) = split /\s+(?=\D)/, $string, 4;
my ( $timeStamp, $log ) = unpack 'A15 A*', $string;
my ( $host, $facility, $msg ) = split /\s+/, $log;
答案 1 :(得分:2)
Parse::Syslog是否可以在没有i-try-this-regexp的情况下做你需要的东西-oh-it-not-work-ok-i-hcanged-and-it-works-oh-not-always -hmm-let-me-try-that-much-better-yay-oh-no-it-broke-let-me-try-this-one-nobody-nobody-done-this-yet feeling?
答案 2 :(得分:1)
使用正则表达式。这是一个简单的例子:
$mystring = "Jan 26 20:53:31 hostname logger: System rebooted for hard disk upgrade";
if($mystring =~ m/(\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2})\s([^\s]*)\s([^\s:]*):\s(.*$)/) {
$date=$1;
$host=$2;
$facility=$3;
$mesg=$4;
print "Date: $date\nHost: $host\nFacility: $facility\nMesg: $mesg";
}
答案 3 :(得分:1)
老问题,但我遇到了类似的问题,并通过格式化我的系统日志消息进行了纠正(因此修改了rsyslog.conf)
我创建了rsyslog模板,如下所示
template(name="CustomisedTemplate" type="list") {
property(name="timestamp")
constant(value=" ")
property(name="$year")
constant(value=";")
property(name="hostname")
constant(value=";")
property(name="programname")
constant(value=";")
property(name="msg" spifno1stsp="on")
property(name="msg" droplastlf="on")
constant(value="\n")
}
然后
我通过添加
将我的自定义模板设置为默认模板 $ActionFileDefaultTemplate CustomisedTemplate.
到(r)syslog.conf
我还可以为我的程序(logger)创建过滤器,它将使用由程序(logger)创建的模板和重定向消息来分隔文件。为此,我添加了
if $programname contains "logger" then /var/logs/logger.err;CustomisedTemplate
到(r)syslog.conf
所以最后我的syslog条目看起来像
Jan 26 20:53:31 2016;hostname;logger:;System rebooted for hard disk upgrade
这很容易解析。