Home > Back-end >  Regex: repeated matches using start of line
Regex: repeated matches using start of line

Time:03-18

Say that I would like to replace all as that are after 2 initial as and that only have as in between it and the first 2 as. I can do this in Vim using the (very magic \v) regex s:\v(^a{2}a{-})@<=a:X:g:

aaaaaaaaaaa

goes to

aaXXXXXXXXX

However, why does s:\v^a{2}a{-}\zsa:X:g only replace the first occurrence? I.e., giving

aaXaaaaaaaa

I presume this is because the first match "consumes" the start of the line and the first 2 as such that later matches only are matching on what remains of the line, which never can match the ^ again. Is this true? Or rather what is the most pedagogical explanation?

P.S. This is a minimal example of another problem.

Edit

Accepted answer corrected a typo in the original regex (a missing ^) and its comment answered the question: why can the ^ be "reused" in the lookbehind but not in the \zs case? (Ans: lookbehind doesn't consume the match whereas \zs does.)

CodePudding user response:

The point here is that (a{2}a{-})@<=a matches any a (see the last a) that is preceded with two or more a chars. In NFA regex flavors, it is equal to (?<=a{2,}?)a, see its demo.

The ^a{2}a{-}\zsa regex matches the start of string, then two or more as, then discards this matched text and matches an a. So, it cannot match other as since the ^ anchors the match at the start of the string (and it does not allow matching anywhere else).

You probably want to go on using a lookbehind construct and add ^ there (if you want to only start matching if the string starts with two as):

:%s/\v(^a{2}a{-})@<=a/X/g
  • Related