我必须解析多个看起来像dmesg输出的日志文件。
示例日志文件:
....
1399424400 4 abcd 2604 starting job (jobid=1325) for client abc.xyz.com, requesting resources now
RESOURCE_GRANTED 1399424400 DiskVolume=/vol;DiskPool=pool1;Path=/mypath;Server=qwer.poil.com;
....
我需要将输出文件打印到jobid,客户端,磁盘卷,磁盘池等,因此输出文件将如下所示:
1325 abc.xyz.com /vol pool1 /mypath qwer.poil.com
<file2 info>
<file3 info>
.....
我尝试这样做以获得jobid:
if(@grepres=grep{/jobid/} <TRY>){
@splitres=split(' ',$grepres[0]);
$jobid=$splitres[1];
$jobid =~ s/\D//g;
fh在哪里。
但它只返回行中的第一个数字,即时间戳。
如何获取客户端名称或服务器名称?
perl是否适合这个?
答案 0 :(得分:1)
如果这些行始终是相同的格式,您可以使用foreach循环并按原样拆分每一行,同时使用该数组访问所需的每个字段。试试这个。
my @logfile = <TRY>;
close TRY;
my $jobid;
foreach my $line (@logfile) {
chomp $line; # remove trailing newline
# might be good to check for blank lines or anything invalid
if ( $line !~ /^$/ ) {
my @splitres=split(' ',$line);
$jobid=$splitres[1];
$jobid =~ s/\D//g;
# and so on with the remaining fields...
}
}
答案 1 :(得分:1)
在重新格式化之前,您应该将每个文件中所需的所有数据都放入哈希值。
此程序以您希望在输出中显示的字段名称列表开头,并构建一个与其后跟其值的字段匹配的正则表达式。
然后,所有必要的是在文件的所有行中找到所有出现的模式,并将它们添加到散列中。
最后检查以确保所有必填字段都在哈希中,然后将内容打印为简单的哈希切片。
请询问您是否有任何不清楚之处。
use strict;
use warnings;
my @names = qw/ jobid client DiskVolume DiskPool Path Server /;
my @files = qw/ dmesg1.txt dmesg2.txt dmesg3.txt /;
my $re = join '|', @names;
$re = qr{ \b($re)\b [\s=]+ ([\w./]+) }x;
for my $filename ( @files ) {
open my $fh, '<', $filename or do {
warn "Can't open '$filename' for reading: $!";
next;
};
my %data;
while ( my $line = <$fh> ) {
$data{$1} = $2 while $line =~ /$re/g;
}
if ( my @missing = grep { not exists $data{$_} } @names ) {
warn sprintf 'Missing %s "%s" from file "%s"',
@missing == 1 ? 'field' : 'fields',
join(', ', @missing),
$filename;
next;
}
print "@data{@names}\n";
}
<强>输出强>
1325 abc.xyz.com /vol pool1 /mypath qwer.poil.com
答案 2 :(得分:0)
Perl正则表达式将是您的完美解决方案。由于它是一个日志文件,我希望格式不会改变,因此您可以轻松使用Perl正则表达式。以下脚本可以帮助您。
#!/usr/bin/perl
open (DATA,"<test") or print "cannot open test file";
open (DATA1,">test1") or print "cannot open test1 file";
while (<DATA>)
{
if ($_=~/.*jobid=(\d+).*client\s*(\w+\.\w+\.\w+).*DiskVolume=(\/\w+).*DiskPool=(\w+).*Path=(\/\w+).*Server=(\w+\.\w+\.\w+).*/)
{
print DATA1 "$1 $2 $3 $4 $5 $6\n";
}
}
close (DATA);
close(DATA1);
我获得的输出是
[root@server perl]# cat test1
1325 abc.xyz.com /vol pool1 /mypath qwer.poil.com