in reply to Replace zero-width grouping?

Move the loop out of the regex.

$_="17341234"; 1 while s/(.)(...)\1/A$2B/; print "$_\n"

Added: Also - if you need to prevent restarting the regex for some reason, you can add some additional code and still get that. The addition of the eval block and the substr() might be more expensive than starting over - I'll leave that to someone else to benchmark. (and on varying size data)

$_="17341234"; $r = 0; 1 while substr($_,$r) =~ s/(.)(...)\1(?{local $r = pos() - 3})/A$2B/; print "$_\n"

Replies are listed 'Best First'.
Re: Re: Replace zero-width grouping?
by tinypig (Beadle) on May 06, 2003 at 20:40 UTC
    Thanks! My wording on the problem was kind of awkward, but if there is any confusion on it, I think what your first example describes the work I want to accomplish perfectly.
Re: Re: Replace zero-width grouping?
by BrowserUk (Patriarch) on May 07, 2003 at 16:31 UTC

    I don't think that your second varient works?

    The problem being that your pos() which is looking at the pos of $_, but you are applying the s/// to an substr lvalue, which is a different animal all together?.

    I could be wrong on this, but I can't seem to get it to work.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

      I tested the code before posting it. It works correctly. It turns out that it works incredibly inefficiently - the longer test string shows that this loops many more times than necessary. I accidentally had the substr() falling off the end and so it had to restart a lot. I've fixed it up and now its super-slick. The substr() always starts right after the position replaced by the 'A'. This will walk the input string and never covers the same ground twice.

      # The instrumented version my $a = "17341234173412341734123417341234"; $expected = "A7AAB2BBA7AAB2BBA7AAB2BBA7AAB2BB"; $r = 0; 1 while substr($a,$r) =~ s/(?{print ">".pos()."$r\n"})(.)(...)\1(?{$r+ +=pos()-4;print"#$r\n"})/A$2B/; print "$a\n$expected\n"; print $a eq $expected ? "Ok\n" : "Failed\n"; # The clean version my $a = "17341234173412341734123417341234"; $r = 0; 1 while substr($a,$r) =~ s/(.)(...)\1(?{$r+=pos()-4;})/A$2B/; print "$a\n"