Frage

First, I apologize if you feel this is a duplicate. I looked around and found some very similar questions, but I either got lost or it wasn't quite what I think I need and therefore couldn't come up with a proper implementation.

QUESTION:

So I have a txt file that contains entries made by another script (I can edit the format for how these entries are generated if you can suggest a better way to format them):

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().

And I made a perl script to parse the file:

#!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;

My goal is to have a hash in the end that looks like this:

$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().',
                },
           },
    },

};

What would be the best way of going about this? Should I change the formatting of the generated logs to make it easier on myself? If you need anymore info, just ask. Thank you in advanced. :)

War es hilfreich?

Lösung

The format makes no sense. You used a hash at the third level, but you didn't specify keys for the values. I'm assuming it should be an array.

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,
      };
   }
}

Should I change the formatting of the generated logs

Your time stamps appear to be ambiguous. In most time zones, an hour of the year is repeated.

Andere Tipps

If you can possibly output it as XML, reading it in would be embarrasingly easy with XML::Simple

Although Karthik T idea of using XML makes sense, and I would also consider it, I'm not sure if this is the best route. The first problem is putting it in XML format in the first place.

The second is that XML format might not be so easily parsed. Sure, the XML::Simple module will read the whole thing in one swoop, you then have to parse the XML data structure itself.

If you can set the output however you want, make it in a format that's easy to parse. I like using prefix data identifiers. In the following example, each piece of data has it's own identifier. The ER: tells me when I hit the end of record:

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:

Parsing this output is straight forward:

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 = ();
    }
}

I like using classes whenever I start getting complex data structures, and I would probably create a Local::Log class and subclasses to store each layer of the log. However, it's not an absolute necessity and wasn't part of your question. Still, I would use a create_entry subroutine just to keep the logic of figuring out where in your log that entry belongs inside your loop.

NOTE: I append a space after each piece of data. I did this to make the code simpler since some of your messages may take more than one line. There are other ways to handle this, but I was trying to keep the loop as clean as possible and with as few if statements as possible.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top