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

Hi Monks, I'm new to Perl and trying to figure out how to only replace matches after the initial match using regex. For example, I would like to replace any matches of bar with foo after finding the first bar.

Input foofoo
Output foobar

I have tried what I believe is look ahead assertion

$s = s/bar(?=bar)/foo/;

However it seems to get rid of everything and print an empty string.

Replies are listed 'Best First'.
Re: Regex match and replace
by kennethk (Abbot) on Mar 04, 2015 at 17:39 UTC
    Is there a reason you need to do it as a compound regular expression? It'll probably be easier to do it as a compound operation with index, substr and a substitution:
    substr($s, 1+index $s, 'bar') =~ s/bar/foo/g;
    You could also run the regular expression repeatedly, using the \K escape.
    while ($var =~ s/bar.*?\Kbar/foo/) {1}
    If you are running an outdated version of Perl, you can do something similar with back references:
    while ($var =~ s/(bar.*?)bar/$1foo/) {1}
    Update: Corrected code, as I had a weird brain fail on reading the spec.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Thank you for your detailed answer, that seems like an interesting way of doing it. Thanks!

Re: Regex match and replace
by AnomalousMonk (Archbishop) on Mar 04, 2015 at 18:04 UTC
    $s = s/bar(?=bar)/foo/;

    This statement does a substitution against the string held in the  $_ default scalar, and assigns to  $s the number of times a substitution occurred. As I do not know what, if anything, was in  $_ when you ran your code, it's hard to tell why the substitution failed (zero substitutions occurred). You may want a statement like
        $s =~ s/bar(?=bar)/foo/;
    which can actually do a substitution on $s.

    Input foofoo
    Output foobar

    I'm confused by this because you write that you want to replace some 'bar' in the input string with 'foo', but there ain't no 'bar' thar! Can you please clarify with exact input and desired output strings?

    Update: Making some assumptions about what the input string might be, it's possible to do what you want using a positive look-behind:

    c:\@Work\Perl>perl -wMstrict -le "my $s = 'barbar'; $s =~ s/(?<=bar)bar/foo/; print qq{'$s'}; " 'barfoo'
    (substitute a 'bar' with 'foo' if it is preceded by a 'bar').


    Give a man a fish:  <%-(-(-(-<

      I see the problem that I had now, thanks for your answer.

Re: Regex match and replace
by hdb (Monsignor) on Mar 04, 2015 at 21:10 UTC

    You could also literally count the number of matches and only start replacing from the second match onwards:

    use strict; use warnings; my $s="foofoo"; my $ctr = 0; $s =~ s/(foo)/$ctr++?"bar":$1/ge; print "$s\n";

      That's pretty neat, thanks!

Re: Regex match and replace
by choroba (Cardinal) on Mar 05, 2015 at 09:20 UTC
    TIMTOWTDI:
    my $s = 'foo|foo|foo'; my $p = do { $s =~ /foo/g; pos $s }; $s =~ s/foo/pos $s >= $p ? 'bar' : 'foo'/ge; print "$s\n";
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ