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

Hi, I'd like to find all occurances of a pattern and its start/end matching positions:
# To find all occurance of "bc" preceeded by 3 letters, and followed b +y 2 letters. $str = "aaabcabcdebcaabebcb"; while($str =~ /(\w{3}bc\w{2})/g){ print "$-[1],$+[1],$1\n"; } __OUTPUT__ 0,7,aaabcab 7,14,cdebcaa
It didn't quite do what I want. I'd like it to match 3 times:
__OUTPUT__ 0,6,aaabcab 3,9,bcabcde 7,13,cdebcaa
Thanks.

Replies are listed 'Best First'.
Re: Regex: continuous matching positions
by Tanktalus (Canon) on Apr 26, 2006 at 15:45 UTC

    Check out the pos function. For example:

    $str = "aaabcabcdebcaabebcb"; while($str =~ /(\w{3}bc\w{2})/g){ print "$-[1],$+[1],$1\n"; pos($str) = $-[1]+1; }
    This sets the position to start looking for the next match to 1 past the start point of the previous match. And it gets you the output you want.

Re: Regex: continuous matching positions
by japhy (Canon) on Apr 26, 2006 at 16:07 UTC
    The problem is that the regex consumes the characters it matches (so the next match happens after those characters). Use a look-aahead to not consume:
    while ($str =~ /(?=(\w{3}bc\w{2}))/g) { print "$-[1],$+[1],$1\n"; }
    Update: extra ')' added to regex (thanks SamCG and prasadbabu!)

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Regex: continuous matching positions
by duff (Parson) on Apr 26, 2006 at 15:48 UTC

    Use zero-width lookahead and lookbehind:

    $str = "aaabcabcdebcaabebcb"; while($str =~ /(?<=\w{3})(bc)(?=\w{2})/g){ print "$-[1],$+[1],$1\n"; }
    update: As my esteemed fellow monk Tankalus reminds me, you'll need to adjust your mechanism for retrieving the exact characters you require.