Basic pattern matching is not the best solution to this situation, but I'll focus on correct pattern matching.

See Programming Perl, Chapter 3, "The Range Operator" (pg 103 in the third edition).

'..' is a boolean operator, which is false by default. Once the left operator returns true, the '..' evaluates to true until the right operator evaluates to true.

As soon as the left operator evaluates to true, stating that the beginning of the range has been reached, the right operator is tested, to see if the end of the active reagion has been reached. That's why you don't get the regions betwween header lines, with '..': as soon as you detect the beginning of the region, it also triggers the end of region.

With '...', end of region is not tested when the start has just been detected, so you do get the regions between the header lines. But since the start and end patterns are the same, and the patterns match several times, you only get some of the regions.

Your file has the structure:

  1. ClientExitPath:
  2. LogDefaults:
  3. QueueManager:
  4. QueueManager:
  5. QueueManager:
  6. QueueManager:

You want to begin printing at header section 3, the first QueueManager. You want to process key/value pairs until you are no longer in a QueueManager section.

Detect the beginning is fine the way you have it. The end of the region you want is marked by encountering a header line which is not a QueueManager header. (Or, of course, end of file) So a simple pattern you want is:

print if /^QueueManager:/ ... (/:/ && ! /^QueueManager:/);

i.e.: Begin printing when you encounter a QueueManager, and continue until you reach a non-QueueManager header line. But this is clumsy and relatively complicated. You COULD be daring and use a closing condition like /^^Q\w*:/, a header line which does not begin with a Q, but what if there's a QueryManager: header line? What you really want is a header line which is not a QueueManager header line. A negative look-behind assertion is perfect for this:

print if /^QueueManager:/ ... /^(?<=:QueueManager):/;

The closing condition is a ':' which follows any string ... any string other than 'QueueManager'.

As a minor style difference, I don't bother matching the '\*$' after the colon.

I typed "negative look-behind assertion", but then in the code I made a typo and used a positive look behind assertion. The code should be /^(?<!:QueueManager):/ ... BUT either a negative or positive look-behind assertion work. How did that happen? Tom

In reply to Re: parsing a config file by TomDLux
in thread parsing a config file by Gorio3721

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.