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

I am trying to use a regular expression to extract text from a large number of .txt files. I have phrases that demarcate the beginning and ending of the piece of text I want to extract. However these phrases are potentially in other parts of the document as well. The specific problem I am trying to tackle is when the beginning phrase is repeated twice without the ending phrase occurring. This leads me to collect more of the text than I want. Hopefully this specific example will help explain my problem.

When I run this code:

$x = "dog 789 cat dog dog bird cat wonder dog frog cat"; @finds = ($x =~ /((?:dog)(?:.*?)(?:cat))/g);

I end up with:

$finds[0] = dog 789 cat $finds[1] = dog dog bird cat $finds[2] = dog frog cat

How do I change my regular expression to skip over the second "dog" and end up with $finds[1] = dog bird cat?

Thanks in advance! Please excuse me if I have broken any protocols. I'm quite new to Perl and this is my first time seeking help here.

Replies are listed 'Best First'.
Re: Rematching within a regular expression
by sauoq (Abbot) on May 11, 2012 at 23:46 UTC

    This may or may not be good in your case...

    #!/usr/bin/perl -l $x = "dog 789 cat dog dog bird cat wonder dog frog cat"; @finds = ($x =~ /((?:dog)(?:.*?)(?:cat))/g); $y = reverse $x; @finds2 = ($y =~ /((?:tac)(?:.*?)(?:god))/g); print for @finds; print "-----"; print scalar reverse for reverse @finds2;

    Ouptuts:

    dog 789 cat dog dog bird cat dog frog cat ----- dog 789 cat dog bird cat dog frog cat

    It's a nice technique to know, anyway. (The credit goes to japhy for it.)

    -sauoq
    "My two cents aren't worth a dime.";
Re: Rematching within a regular expression
by Anonymous Monk on May 12, 2012 at 03:24 UTC
    Use a negative look-ahead:
    $_ = "dog 789 cat dog dog bird cat wonder dog frog cat"; my @finds = /(dog(?:(?!dog).)*?cat)/g; say Dumper \@finds;
    Outputs:
    [ "dog 789 cat", "dog bird cat", "dog frog cat" ]