ciryon has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks! I'm trying to parse a logfile and put the contents into a hash. Part of the file looks like:
Handle_Bogus_Timeout 36 TimerList 4 ResetOneHundredmSecondTimerReport 8 ResetTimer 16 SetOneHundredmSecondTimer 12 SetTimer 16
As you can see it's not allways one key and one value per line. If the key is too long it'll have the value on a new line. I'm going through each line with
if(/(\S+)\s+(\d+)/)
to check if it's valid, else it should do something to take care of the incorrect lines. Suggestions?

Replies are listed 'Best First'.
Re: Key, newline, value problem
by Happy-the-monk (Canon) on Jun 22, 2004 at 08:50 UTC

    use the /s (or /m) and /g modifiers to treat the string as a single line (or as multiple lines) and get multiple matches:

    my @matches =~ m/(\S+)\s+(\d+)/mg; # or /sg
    if ( @matches ) { ...

    Update: even better using a hash:

    my %matches =~ m/(\S+)\s+(\d+)/sg; # or /mg
    foreach ( keys %matches ) { ...

    Update 2: Added small print /s ( + /m ) ambiguity...
    See   perldoc perlre   for more info on perl regular expressions and those and other flags.

    Cheers, Sören

Re: Key, newline, value problem
by BrowserUk (Patriarch) on Jun 22, 2004 at 09:21 UTC

    open LOG, '<', 'the/log' or die $!; my %hash = do{ local $/; split ' ', <LOG> }; close LOG;

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: Key, newline, value problem
by Zaxo (Archbishop) on Jun 22, 2004 at 08:50 UTC

    Something like this should do:

    # in while (<$fh>) {...} my ($key, $value) = split; if ( ! defined $value ) { ($value = <$fh>) =~ s/^\s*(\d+)\s*$/$1/; } # . . .

    After Compline,
    Zaxo

Re: Key, newline, value problem
by Hena (Friar) on Jun 22, 2004 at 08:51 UTC
    Well, you can get the value with simple flagging. This should be ok (untested).
    while (<>) { if ($key) { m/(\d+)/ $hash{$key}=$1; $key=""; } elsif (/(\S+)\s+(\d+)/) { $hash{$1}=$2 } else { m/(\s+)/ $key=$1; } }