Take a file with the following text as a workbench.
hello world hello world
With the cursor at the beginning of the line, here's how \1
interacts with \(…\)
, \@=
, and \@!
# | regex | matched text | text matched by \1 |
why |
---|---|---|---|---|
1 | \(world\).*\1 |
world hello world |
world |
which is what \(…\) is matching |
2 | \(world\)\@=.*\1 |
world hello world |
world |
which is what \(…\) is matching even though \@= makes it zero-width |
3 | \%(world\).*\1 |
nothing (E65: Illegal back reference ) |
not valid | as \%(…\) forgets the match |
4 | \%(world\)\@=.*\1 |
nothing (E65: Illegal back reference ) |
not valid | as \%(…\) forgets the match |
5 | \(world\)\@!.*\1 |
the whole line? | any zero-width position, i.e. everywhere? | |
6 | \(world\)\@!.* |
the whole line | n.a. | |
7 | \(world\)\@!.*\1\1 |
the whole line? | any zero-width position, i.e. everywhere? | |
8 | \(world\)\@!.*\1\1\1 |
the whole line? | any zero-width position, i.e. everywhere? |
As it's clear from #5, I don't understand what \1
is doing in \(world\)\@!.*\1
:
- from #2, I would say that
\(world\)
matchesworld
even if the\@=
after it makes it consume no text, - so I would have expected the same was true when applying
\@!
, but that appears not to be the case from #5 - and the difference is not that
\1
is invalid, as proved by #3 and #4 - #6 tells us that
\1
in #5 (and #7 and #8) is matching anywhere with zero width
Any idea?
The documentation doesn't seem to help.
(?=world).*\1
, this will report an error:\1
references a non-existent or invalid subpattern. We can use(?=(world)).*\1
, which is equivalent to\(world\)\@=.*\1
in Vim. Following this line of thought, we can test(?!(world)).*\1
in other flavor by regex101.com. We will find similar or strange results in other languages. So the issue you listed above is not only in Vim, this seems to be a common problem with all regex engines processing.