Say that I would like to replace all a
s that are after 2 initial a
s and that only have a
s in between it and the first 2 a
s. 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 a
s 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 a
s, then discards this matched text and matches an a
. So, it cannot match other a
s 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 a
s):
:%s/\v(^a{2}a{-})@<=a/X/g