[TriLUG] Negative search in Vi
Michael Tharp
gxti at partiallystapled.com
Sat Apr 12 19:09:16 EDT 2008
Craig Taylor wrote:
> Negate your regular expression search, eg: for lines that don't have 'dog'
> use :
>
> /^.*[^d][^o][^g].*$
>
> disclaimer: this has not been tested - I believe it should work 'tho)
>
> - Craig Taylor
>>> foo = re.compile('^.*([^d][^o][^g]).*$')
>>> sample = 'the quick brown fox jumped over the lazy dog'
>>> bool(foo.search(sample))
True
>>> foo.search(sample).groups()
(' do',)
The problem here is this:
1. The first ".*" gobbles up everything up to "dog"
2. [^d][^o][^g] doesn't match "dog", so it backtracks by one character
to " do"
3. It matches, since " do" != "dog"
4. The second ".*" gobbles up the remainder of the string
Doing negative matches is surprisingly difficult and I honestly can't
say I know of a way to do this with just a regular expression, either.
Aaron's suggestion of deleting all matching lines and stepping through
the remainder is probably the most plausible. Honestly, if this is
possible, it has to be a feature of vim itself, not some regex trickery.
As I wrote this, Kevin posted a recommendation for lookahead/behind
assertions, but remember that those only work if you have something to
anchor them to! You can't say "match anything but dog" with an assertion
unless you have something that you *do* match first, and then say "match
if it is not followed by dog". In Kevin's example, the anchor is the end
of the string, but this is insufficient for simply checking whether
something is not present if it could be anywhere in the middle.
-- m. tharp
More information about the TriLUG
mailing list