in reply to Shift regex search back 4 characters...

G'day tj999,

Welcome to the Monastery.

Before seeing other responses, my first thought was a lookbehind assertion:

/(?<=222,)(\d{3})/g

Having seen other solutions, I think this is clearer than embedding a capture in an assertion.

Here are some tests using your example string and the two others used in earlier replies.

$ perl -E 'say for "222,222,123" =~ /(?<=222,)(\d{3})/g' 222 123 $ perl -E 'say for "222,345,222,678,222,222,543,111" =~ /(?<=222,)(\d{ +3})/g' 345 678 222 543 $ perl -E 'say for "123,222,456,222,222,111,222,999" =~ /(?<=222,)(\d{ +3})/g' 456 222 111 999

— Ken

Replies are listed 'Best First'.
Re^2: Shift regex search back 4 characters...
by BillKSmith (Monsignor) on Mar 04, 2017 at 15:37 UTC
    I prefer your lookbehind solution, but I expect tybalt89 will prefer the lookahead because it solves the problem the way he expected ("move back 4 characters after finding a match")
    Bill

      I doubt that tybalt89 expected any sort of backward movement because I think he or she understands the point illustrated by Athanasius here that a zero-width assertion simply does not move the match start-position at all even if it should happen to capture something. Just for grins, here's a solution that actually does move the match position backwards, although I don't think it will be much to your taste:

      c:\@Work\Perl\monks>perl -wMstrict -le "$_ = '222,345,222,678,222,223,224,222,543'; ;; 1 while m{ 22[234] , (*MARK:BACK3) (\d\d\d) (?{ print qq{'$^N'} }) (*SKIP:BACK3) (*FAIL) }xmsg; " '345' '678' '223' '224' '222' '543'
      Please see Special Backtracking Control Verbs in perlre from Perl version 5.10 onward.

      BTW: One reason tybalt89's first thought was for a look-ahead may have been that Perl's regex engine does not support variable-width look-behind, so using a look-behind may simply be a prelude to a re-write that switches to using a look-ahead when a need for some variability is discovered.


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