Home Explore Blog CI



neovim

10th chunk of `runtime/doc/pattern.txt`
5000eafd43e795256afb1677486ae202161f65f3090e2a4f0000000100000fa2
 check if a match can be
	made.  This can be tricky, because a match with following items will
	be done in the same position.  The last example above will not match
	"foobarfoo", because it tries match "foo" in the same position where
	"bar" matched.

	Note that using "\&" works the same as using "\@=": "foo\&.." is the
	same as "\(foo\)\@=..".  But using "\&" is easier, you don't need the
	parentheses.


							*/\@!*
\@!	Matches with zero width if the preceding atom does NOT match at the
	current position. |/zero-width|
	Like "(?!pattern)" in Perl.
	Example			matches ~
	foo\(bar\)\@!		any "foo" not followed by "bar"
	a.\{-}p\@!		"a", "ap", "app", "appp", etc. not immediately
				followed by a "p"
	if \(\(then\)\@!.\)*$	"if " not followed by "then"

	Using "\@!" is tricky, because there are many places where a pattern
	does not match.  "a.*p\@!" will match from an "a" to the end of the
	line, because ".*" can match all characters in the line and the "p"
	doesn't match at the end of the line.  "a.\{-}p\@!" will match any
	"a", "ap", "app", etc. that isn't followed by a "p", because the "."
	can match a "p" and "p\@!" doesn't match after that.

	You can't use "\@!" to look for a non-match before the matching
	position: "\(foo\)\@!bar" will match "bar" in "foobar", because at the
	position where "bar" matches, "foo" does not match.  To avoid matching
	"foobar" you could use "\(foo\)\@!...bar", but that doesn't match a
	bar at the start of a line.  Use "\(foo\)\@<!bar".

	Useful example: to find "foo" in a line that does not contain "bar": >
		/^\%(.*bar\)\@!.*\zsfoo
<	This pattern first checks that there is not a single position in the
	line where "bar" matches.  If ".*bar" matches somewhere the \@! will
	reject the pattern.  When there is no match any "foo" will be found.
	The "\zs" is to have the match start just before "foo".

							*/\@<=*
\@<=	Matches with zero width if the preceding atom matches just before what
	follows. |/zero-width|
	Like "(?<=pattern)" in Perl, but Vim allows non-fixed-width patterns.
	Example			matches ~
	\(an\_s\+\)\@<=file	"file" after "an" and white space or an
				end-of-line
	For speed it's often much better to avoid this multi.  Try using "\zs"
	instead |/\zs|.  To match the same as the above example:
		an\_s\+\zsfile
	At least set a limit for the look-behind, see below.

	"\@<=" and "\@<!" check for matches just before what follows.
	Theoretically these matches could start anywhere before this position.
	But to limit the time needed, only the line where what follows matches
	is searched, and one line before that (if there is one).  This should
	be sufficient to match most things and not be too slow.

	In the old regexp engine the part of the pattern after "\@<=" and
	"\@<!" are checked for a match first, thus things like "\1" don't work
	to reference \(\) inside the preceding atom.  It does work the other
	way around:
	Bad example			matches ~
	\%#=1\1\@<=,\([a-z]\+\)		",abc" in "abc,abc"

	However, the new regexp engine works differently, it is better to not
	rely on this behavior, do not use \@<= if it can be avoided:
	Example				matches ~
	\([a-z]\+\)\zs,\1		",abc" in "abc,abc"

\@123<=
	Like "\@<=" but only look back 123 bytes.  This avoids trying lots
	of matches that are known to fail and make executing the pattern very
	slow.  Example, check if there is a "<" just before "span":
		/<\@1<=span
	This will try matching "<" only one byte before "span", which is the
	only place that works anyway.
	After crossing a line boundary, the limit is relative to the end of
	the line.  Thus the characters at the start of the line with the match
	are not counted (this is just to keep it simple).
	The number zero is the same as no limit.

							*/\@<!*
\@<!	Matches with zero width if the preceding atom does NOT match just
	before what follows.  Thus this matches if there is no position in the
	current or previous line where the atom matches such that it ends just
	before what follows.  |/zero-width|
	Like

Title: Vim Regular Expression Zero-Width Matches: @!, @<=, @<!
Summary
This section discusses zero-width matching items in Vim regular expressions, specifically @!, @<=, and @<!. These items allow matching based on whether a pattern does or does not match at the current or preceding position without including the matched characters in the overall match. It provides examples and explanations of their behavior, limitations, and potential performance considerations, particularly regarding look-behind assertions.