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

Good day,monks.
It's not the first time I ask about this..
The folloing is the example of files with commands.
Start context
duplex
Half
Pass level = 2
negotiation
Pass level = 2
back-pressure
Pass level = 2
* Exit context *
There are many different contexts in this file.But they all end with the line "* Exit context *". What I need is to be able to to parse the lines between the closest "START Context" and "* END context *" at the time.
If I use the following code:
open DATA,"c://xxx.txt"; while(<DATA>) { if (/START context/ .. /* End Context */ ) { print unless /(START context |* End context *)/; } }
It prints all the lines (except what is in unless of course) between the first "Start context" and the last "* End context *". I tried to use non-greedy regular expression (.*?) ,but still didn't get the desired result. Can someone please help?
Thanks a lot in advance.

Edit by castaway, added code tags

Replies are listed 'Best First'.
Re: I still can't get only the necessary lines from the file.
by davido (Cardinal) on Jul 01, 2004 at 06:35 UTC

    One problem is your regexp. Here's what it is saying:

    Match if:

    1. Match "START context"
    2. or
    3. * is a quantifier, and can't be used as a bare character without escaping it. In the context of |*, I have no idea how it's going to be interpreted, but it won't be how you think.
    4. Match "End context"
    5. Match any amount of trailing space characters (because you used * again, which is a quantifier).

    The "print unless..." statement should be as follows:

    print unless ( /START context/ or /\* End context \*/ );

    Another solution might be like this:

    { local $/ = "* End Context *\n"; while ( <DATA> ) { s/^START context//; my @info = split /\n/; chomp @info; print "$_\n" foreach @info }

    Dave

Re: I still can't get only the necessary lines from the file.
by gaal (Parson) on Jul 01, 2004 at 06:32 UTC
    * is a metacharacter. Try escaping it in your regexps:
    if (/START context/ .. /\* End Context \*/) { print unless /START context|\* End Context \*/; }
    Also, note that your data says "Exit" but your code looks for "End".
Re: I still can't get only the necessary lines from the file.
by ercparker (Hermit) on Jul 01, 2004 at 06:52 UTC
    in your text file example you have Start context and * Exit context *
    in your code you're matching for START context and End context
    I modified the code to match correct, tested, and works fine:
    will print everything except what your matching for in the print unless
    open (DATA,"<c://xxx.txt") || die "Can't open xxx.txt: $!\n"; while(<DATA>) { if (/Start context/ .. /\* End Context \*/) { print unless /(Start context|\* Exit context \*)/; } }
      Oops -my mistake.I have the correct line in my code's unless. \* Exit context \*
      The problem is that in print results I get lines that are not between the closest "Start context" and "* end context *".
      I suspect that maybe the problem is in this line:
      if (/Start context/ .. /\* End Context \*/)
      which IMHO takes all the lines between the first "Start context" in the file and last "* end context *"
      . Am I right? Or the line:
      if (/Start context/ .. /\* End Context \*/)
      looks for the closest "Start context" and "* End context *"
      Thanks
        The .. "flip-flop" operator (see perlop) is true "between" the two operands. That is, once the left-hand match is true, the flip-flop is true, until whenever the right-hand match succeeds. Then it's false until the left-hand match is true, and so on.

        So, no: if (/Start context/ .. /\* End Context \*/) { doesn't "take" "all the lines between the first 'Start context' in the file and last '* end context *'", but indeed only those within any of the contexts (and the start marker too, but not the end marker).
Re: I still can't get only the necessary lines from the file.
by Anonymous Monk on Jul 01, 2004 at 06:37 UTC
    perl -e '/(START context |* End context *)/' Quantifier follows nothing in regex; marked by <-- HERE in m/(START co +ntext |* <-- HERE End context *)/ at -e line 1.
    What do you think is wrong here? perldoc perlre
Re: I still can't get only the necessary lines from the file.
by muba (Priest) on Jul 01, 2004 at 09:38 UTC
    Would you please, please use <code> tags?
Re: I still can't get only the necessary lines from the file.
by ercparker (Hermit) on Jul 01, 2004 at 15:02 UTC
    I think I understand now
    you want the text between the first Start and first Exit
    you can throw in a last to exit the loop when matching Exit
    open (DATA,"<xxx.txt") || die "Can't open xxx.txt: $!\n"; while(<DATA>) { if (/Start context/ .. /\* Exit context \*/) { print unless /(Start context|\* Exit context \*)/; last if /\* Exit context \*/; } }
Re: I still can't get only the necessary lines from the file.
by sashac88 (Beadle) on Jul 01, 2004 at 08:12 UTC
    Sorry ,My mistake.I have the correct line in my code's unless. \* Exit context \* The problem is that in print results I get lines that are not between the closest "Start context" and "* end context *". I suspect that maybe the problem is in this line: if (/Start context/ .. /\* End Context \*/) which IMHO takes all the lines between the first "Start context" in the file and last "* end context *" . Am I right? Or the line: if (/Start context/ .. /\* End Context \*/) looks for the closest "Start context" and "* End context *" Thanks