Perl - 从文本文件中解析块

时间:2012-11-06 01:14:16

标签: regex perl parsing logging filehandler

首先,如果您认为这是重复,我道歉。我环顾四周,发现了一些非常相似的问题,但我要么输了,要么就是我认为我不需要的,因此无法提出正确的实施方案。

问题:

所以我有一个txt文件,其中包含由另一个脚本创建的条目(如果您可以建议更好的格式化方法,我可以编辑这些条目生成方式的格式):

SR4 Pool2
11/5/2012 13:45
----------
Beginning Wifi_Main().

SR4 Pool2
11/8/2012 8:45
----------
This message is a
multiline message.

SR4 Pool4
11/5/2012 14:45
----------
Beginning Wifi_Main().

SR5 Pool2
11/5/2012 13:48
----------
Beginning Wifi_Main().

我制作了一个perl脚本来解析文件:

#!C:\xampp-portable\perl\bin\perl.exe

use strict;
use warnings;
#use Dumper;

use CGI 'param','header';
use Template;
#use Config::Simple;

#Config::Simple->import_from('config.ini', \%cfg);

my $cgh = CGI->new;
my $logs = {};
my $key;

print "Content-type: text/html\n\n"; 

open LOG, "logs/Pool2.txt" or die $!;


while ( my $line = <LOG> ) {
    chomp($line);

}

print $logs;

close LOG;

我的目标是最终得到一个哈希:

$logs = {
    SR4 => {
           Pool2 => {
                {
                    time => '11/5/2012 13:45',
                    msg  => 'Beginning Wifi_NDIS_Main().',
                },
                {
                    time => '11/8/2012 8:45',
                    msg  => 'This message is a multiline message.',
                },
           },
           Pool4 => {
                {
                    time => '11/5/2012 13:45',
                    msg  => 'Beginning Wifi_NDIS_Main().',
                },
           },
    },
    SR5 => {
           Pool2 => {
                {
                    time => '11/5/2012 13:45',
                    msg  => 'Beginning Wifi_NDIS_Main().',
                },
           },
    },

};

最好的解决方法是什么?我应该更改生成的日志的格式以使自己更容易吗?如果您需要更多信息,请询问。先谢谢你。 :)

3 个答案:

答案 0 :(得分:2)

如果您可以将其输出为XML,那么使用XML::Simple

读取它会非常容易

答案 1 :(得分:2)

这种格式毫无意义。您在第三级使用了哈希,但未指定值的键。我假设它应该是一个数组。

my %logs;
{
   local $/ = "";  # "Paragraph mode"
   while (<>) {
      my @lines = split /\n/;
      my ($x, $y) = split ' ', $lines[0];
      my $time = $lines[1];
      my $msg = join ' ', @lines[3..$#lines];
      push @{ $logs{$x}{$y} }, {
         time => $time,
         msg  => $msg,
      };
   }
}
  

我应该更改生成的日志的格式

您的时间戳似乎含糊不清。在大多数时区,一年中的一小时都会重复。

答案 2 :(得分:0)

尽管Karthik T使用XML的想法是有意义的,我也会考虑它,但我不确定这是否是最好的路径。第一个问题是首先将其置于XML格式。

第二个是XML格式可能不那么容易解析。当然,XML :: Simple模块将一举读取整个内容,然后您必须解析XML数据结构本身。

如果您可以根据需要设置输出,请使用易于解析的格式。我喜欢使用前缀数据标识符。在以下示例中,每条数据都有自己的标识符。当我到达记录结尾时,ER:告诉我:

DT: 11/5/2012 13:35
SR: SR4
PL: Pool2
MG: Beginning Wifi_Main().
ER:
DT: 1/8/2012 8:45
SR: SR4
PL: Pool2
MG: This message is a
MG: multiline message.
ER:

解析此输出是直截了当的:

my %hash;
while ( $line = <DATA> ) {
    chomp $line;
    if ( not $line eq "ER:" ) {
        my ($key, $value) = split ( ": ", $line );
        $hash{$key} .= "$value ";   #Note trailing space!
    }
    else {
        clean_up_hash ( \%hash ); #Remove trailing space on all values
        create_entry ( \%log, \%hash );
        %hash = ();
    }
}

每当我开始获得复杂的数据结构时,我都喜欢使用类,我可能会创建一个Local::Log类和子类来存储日志的每一层。但是,这不是绝对必要的,也不是你问题的一部分。尽管如此,我还是会使用一个create_entry子程序来保持逻辑,找出你的日志中你的循环中的条目所在的位置。

注意:我在每个数据后附加一个空格。我这样做是为了使代码更简单,因为你的一些消息可能需要多行。还有其他方法可以解决这个问题,但我试图尽可能保持循环尽可能清晰,尽可能少if个语句。