使用perl从文本文件中提取信息

时间:2014-05-12 23:41:11

标签: perl

我必须解析多个看起来像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是否适合这个?

3 个答案:

答案 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