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

Oh wise Monks of Perl, I beseech thee, pray teach me your wise and mysterious ways. The following snippet of code
use strict; use warnings; my $str = "In this example, A plus B equals C, D plus E plus F equals +G and H plus I plus J plus K equals L"; my $word = "plus"; my @results = (); 1 while $str =~ s/(.{2}\b$word\b.{2})/push(@results,"$1\n")/e; print @results;
Produces the following output:
bash> perl resample.pl A plus B D plus E 2 plus F H plus I 4 plus J 5 plus K
What I want to see is this, where a character already matched can appear in a different context:
A plus B D plus E E plus F H plus I I plus J J plus K
What magic do I need to add to the regular expression to get this result? Thanks oh wise Monks.

Replies are listed 'Best First'.
Re: Regular Expression rematch
by ikegami (Patriarch) on Aug 16, 2009 at 01:56 UTC
    You're replacing parts of the string with the result of push .... Why are you using s/// at all? A simple solution:
    my @results; push @results, "$1$2" while $str =~ /(\S+\s+\Q$word\E)(?=(\s+\S+))/g; print "$_\n" for @results;
      Or even:
      my @results = $str =~ m{ (?= (\S+ \s+ \Q$word\E \s+ \S+) ) }xmsg;
        That won't work if the term is longer than one character, so you might as well change
        my @results = $str =~ m{ (?= (\S+ \s+ \Q$word\E \s+ \S+) ) }xmsg;
        to
        my @results = $str =~ m{ (?= (\S \s+ \Q$word\E \s+ \S+) ) }xmsg;
        Or if you want longer terms:
        my @results = $str =~ m{ (?<! \S ) (?= (\S+ \s+ \Q$word\E \s+ \S+) ) } +xmsg;