http://qs321.pair.com?node_id=638544

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

Hi Monks,
pls help me check this issues: E.g:
$d = "123456789"; $d =~ s/(?<=\d)(?=(\d\d)+$)/-/g; print "$d";
It produce "1-23-45-67-89" ,it is OK.
But on the contrary,I wanna get a "left-to-right" substitution.That is ,i want to get "12-34-56-78-9"
I try :
$d =~ s/(?<=^(\d\d)+)(?=\d)/-/g;
It can't work.Where does it wrong? The wrong log:
Variable length lookbehind not implemented in regex; marked by <-- HER +E in m/(?<=^(\d\d)+)(?=\d) <-- HERE / at Noname1.pl line 4.
TIA.
Pysome

Replies are listed 'Best First'.
Re: Another puzzled RegEx Problem.
by ikegami (Patriarch) on Sep 12, 2007 at 13:29 UTC

    Like the error message says, a limitation of (?<=re) and (?<!re) is that re must only match expressions of a known, fixed length. That means you can use ?, *, +, etc in re. Basically, the regexp engine needs to know how many characters to look back.

    Some alternatives:

    $d =~ s/(\d\d)(?=\d)/$1-/g;
    1 while $d =~ s/(?<=\d\d)(?=\d)/-/;
    $d = reverse($d); $d =~ s/(?<=\d)(?=(\d\d)+$)/-/g; $d = reverse($d);

    Update: Added solutions.

Re: Another puzzled RegEx Problem.
by Fletch (Bishop) on Sep 12, 2007 at 13:32 UTC

    Lookbehind has to be a fixed width; yours isn't (the + quantifier) so it's an invalid regex.

    This is a little kludgy, but will work:

    my $str = "123456789"; $str = reverse $str; $str =~ s/(?<=\d)(?=(\d\d)+$)/-/g; $str = reverse $str; print $str, "\n";
Re: Another puzzled RegEx Problem.
by Prof Vince (Friar) on Sep 12, 2007 at 16:53 UTC
    Substitutions aren't everything. How about :
    my $d = "123456789"; $d = join "-", $d =~ /(\d{1,2})/g;
      Yes.
Re: Another puzzled RegEx Problem.
by shmem (Chancellor) on Sep 12, 2007 at 13:33 UTC
    I wanna get a "right-to-left" substitution.
    See reverse.
    $d = reverse "123456789"; $d =~ s/(?<=\d)(?=(\d\d)+$)/-/g; print scalar reverse "$d\n";
    update: added obvious solution

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Another puzzled RegEx Problem.
by johnlawrence (Monk) on Sep 12, 2007 at 13:59 UTC
    This should also work, though I did like the previous solution of using reverse.
    $d =~ s/(\d\d)(?=\d)/$1-/g;
    Update: Doh! Already posted above. Guess I should refresh more often!
Re: Another puzzled RegEx Problem.
by artist (Parson) on Sep 12, 2007 at 15:11 UTC
    No solution here, but the challenge would be to find the solution that has
    • No while
    • No reverse
    • No $1 etc in substitution part
    --Artist

      No external loop, no reverse and nothing but "-" in the substitution part:

      $d =~ s/(?!^|$)(?(?{ pos() % 2 })(?!))/-/g;

      Update: Bug fix. I originally forgot to prevent "-" from being placed at the end.

        cool