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

I'm trying to parse these logfile records and I can't get the "Secondary Sector Informaton" data parse correctly. This is my program I made when I asked for Record Parsing Advice

Why is "Secondary Sector Information" and "Slot" showing up in the output and how can I get it out? No matter what I do, the match isn't working like I think it should.

Below the code is the acual output and the output I'm trying to get.
use strict; use warnings; local $/= "\n="; while (my $line = <DATA>) { print "\n------------------------------\n"; if ($line =~ m/Primary \(Reporting\) Cp\s*:\s*((?:(?!Set).)*)Set\s*:\s +*((?:(?!Car).)*)Car\s*:\s*((?:(?!Ref).)*)/si) { print "Cp:$1 - Set:$2 - Car:$3"; } if ($line =~ m/Phase\s*:\s*((?:(?!Strength).)*)Strength\s*:\s*((?:(?!\ +n).)*)/si) { print "\nPhase:$1 - Strength:$2\n"; } while ($line =~ m/(?<!Primary \(Reporting\) )(?<!Secondary Sector)Keep +\s*:\s*((?:(?!offset).)*)offset\s*:\s*((?:(?!Strength).)*)Strength\s* +:\s*((?:(?!Ref).)*)/gsi) { print "Keep:$1 - offset:$2 - Strength:$3\n"; } print "\n------------------------------\n"; } __DATA__ ==================================================================== Record: 9851329 Version: 2 Timestamp: Sat Feb 11 22:39:43 2006 Primary (Reporting) Cp: 113 Set: 2 Car: 1 Ref: yes Event: 9922 Missing P: Keep: 1 Phase: 0x2fdf Strength: 24 Secondary Sector Information: ==================================================================== Record: 9851330 Version: 2 Timestamp: Sat Feb 11 22:39:43 2006 Primary (Reporting) Cp: 115 Set: 1 Car: 2 Ref: yes Event: 9923 Missing P: Keep: 1 Phase: 0x7d10 Strength: 31 Secondary Sector Information: Slot 1: Keep: 1 offset: 391 Strength: 27 Ref: no Slot 2: Keep: 1 offset: 325 Strength: 38 Ref: no

Here is what my incorrect output looks like:
------------------------------ Cp:113 - Set:2 - Car:1 Phase:0x2fdf - Strength:24 ------------------------------ ------------------------------ Cp:115 - Set:1 - Car:2 Phase:0x7d10 - Strength:31 Keep:1 Phase: 0x7d10 Strength: 31 Secondary Sector Information: Slot 1: Keep: 1 - offset:391 - Strength:27 Keep:1 - offset:325 - Strength:38 ------------------------------


And it should look like this

------------------------------ Cp:113 - Set:2 - Car:1 Phase:0x2fdf - Strength:24 ------------------------------ ------------------------------ Cp:115 - Set:1 - Car:2 Phase:0x7d10 - Strength:31 Keep:1 Phase: 0x7d10 Strength: 31 Keep:1 - Pn_offset:391 - Strength:27 Keep:1 - Pn_offset:325 - Strength:38 ------------------------------

Replies are listed 'Best First'.
Re: Need help modifying parse program.
by TedPride (Priest) on Mar 04, 2006 at 18:26 UTC
    I'm not even going to try reading through those regex. Why not make things simpler and do something more like:
    use strict; use warnings; my %d; while (<DATA>) { if (m/^Primary \(Reporting\) Cp:/) { ($d{'cp'}) = m/Cp: (\d+)/s; ($d{'set'}) = m/Set: (\d+)/s; ($d{'car'}) = m/Car: (\d+)/s; print "Cp:$d{'cp'} - Set:$d{'set'} - Car:$d{'car'}\n"; } elsif (m/^Missing P:/) { ($d{'keep'}) = m/Keep: (\d+)/s; ($d{'phase'}) = m/Phase: (\w+)/s; ($d{'strength'}) = m/Strength: (\d+)/s; print "Phase:$d{'phase'} - Strength:$d{'strength'}\n"; } elsif (m/Secondary Sector Information:/) { print "Keep:$d{'keep'} - Phase:$d{'phase'} - Strength:$d{'stre +ngth'}\n"; } elsif (m/^Slot/) { ($d{'keep'}) = m/Keep: (\d+)/s; ($d{'offset'}) = m/Offset: (\w+)/s; ($d{'strength'}) = m/Strength: (\d+)/s; print "Keep:$d{'keep'} - Pn_offset:$d{'phase'} - Strength:$d{' +strength'}\n"; } elsif (m/^={68}/) { %d = (); print '-'x30, "\n"; } } print '-'x30, "\n"; __DATA__ ==================================================================== Record: 9851329 Version: 2 Timestamp: Sat Feb 11 22:39:43 2006 Primary (Reporting) Cp: 113 Set: 2 Car: 1 Ref: yes Event: 9922 Missing P: Keep: 1 Phase: 0x2fdf Strength: 24 Secondary Sector Information: ==================================================================== Record: 9851330 Version: 2 Timestamp: Sat Feb 11 22:39:43 2006 Primary (Reporting) Cp: 115 Set: 1 Car: 2 Ref: yes Event: 9923 Missing P: Keep: 1 Phase: 0x7d10 Strength: 31 Secondary Sector Information: Slot 1: Keep: 1 offset: 391 Strength: 27 Ref: no Slot 2: Keep: 1 offset: 325 Strength: 38 Ref: no
Re: Need help modifying parse program.
by GrandFather (Saint) on Mar 04, 2006 at 19:48 UTC

    I strongly recommend using the /x flag with your large regexen to make them more readable and maintainable. It can help code readability to put the regex into a variable too so the flow logic can be seen easily. Consider:

    use strict; use warnings; my $regex = qr| Primary\s\(Reporting\)\s Cp\s*:\s*((?:(?!Set).)*) # Now we can see what's happening Set\s*:\s*((?:(?!Car).)*) # but why are the look aheads needed? Car\s*:\s*((?:(?!Ref).)*) |six; while (<DATA>) { next if $_ !~ $regex; print; }

    Prints:

    Primary (Reporting) Cp: 113 Set: 2 Car: 1 Ref: yes Event: 9922 Primary (Reporting) Cp: 115 Set: 1 Car: 2 Ref: yes Event: 9923

    Note, this is not an attempt to solve you immediate problem - others have done that. It is simply a demonstration of a couple of coding tips.


    DWIM is Perl's answer to Gödel
Re: Need help modifying parse program.
by matze (Friar) on Mar 04, 2006 at 18:44 UTC
    You have got the "Secondary Sector Informaton" and the "Slot" in there because you're matching everything from "Keep:" to "offset" in your inner while loop, so the first match of $1 in the second block becomes
    Phase: 0x7d10 Strength: 31 Secondary Sector Information: Slot 1: Keep: 1 -
    I would replace the last while loop with something simpler like
    map { if ( $_ =~ m/Keep:\s*(\d+)\s*(Phase|offset):\s*([xabcdef\d]+)\s*St +rength:\s*(\d+)/ ) { print "Keep:${1} - ${2}:${3} - Strength:${4}\n"; } } split /\r\n|\n/, $line;