Matching a non-match

34 views
Skip to first unread message

A. Wik

unread,
Dec 20, 2020, 6:09:47 AM12/20/20
to vim_use
Hi all,

Browsing a directory listing, sometimes I hit lines like these:
./spool/exim/input/1FM8sl-00004n-Ix-H
./spool/exim/input/1FM8sn-00004u-OF-D
./spool/exim/input/1E9dsQ-00004f-MO-D
[... thousands of similar lines ...]

How can I use "/" to find the next line not matching the above
pattern? I've tried the following (and several variations):
/\(.*exim.input\)\@<!.*

Regards,
Albert Wik.

Sven Guckes

unread,
Dec 20, 2020, 8:53:59 AM12/20/20
to vim_use
* A. Wik <awi...@gmail.com> [2020-12-20 14:39]:
workaround:
open the file with "less" and right after initiating search with '/'
type '!' and the prompt will switch to "Non-match /". now enter
eg "spool.exim.input" and less will skip all those lines. :-)
that's one of the features i dearly miss with vim. oh, well.

Sven

--
LESS 563 | https://github.com/gwsw/less.git
SEARCHING: | http://www.greenwoodsoftware.com/less/
A search pattern may begin with one or more of:
^N or ! Search for NON-matching lines.
^E or * Search multiple files (pass thru END OF FILE).
^F or @ Start search at FIRST file (for /) or last file (for ?).
^K Highlight matches, but don't move (KEEP position).
^R Don't use REGULAR EXPRESSIONS.
signature.asc

Charles Campbell

unread,
Dec 20, 2020, 10:55:34 AM12/20/20
to A. Wik, vim...@googlegroups.com
Hello:

You could use LogiPat: :LP !"exim/input" and find the next line. Or, you
could use :LPE !"exim/input" and be given the expresson LogiPat used.
LogiPat comes with vim, by the way.

Regards,
Chip Campbell

Tim Chase

unread,
Dec 20, 2020, 12:21:55 PM12/20/20
to Sven Guckes, vim...@googlegroups.com
On 2020-12-20 14:53, Sven Guckes wrote:
> workaround:
> open the file with "less" and right after initiating search with '/'
> type '!' and the prompt will switch to "Non-match /". now enter
> eg "spool.exim.input" and less will skip all those lines. :-)
> that's one of the features i dearly miss with vim. oh, well.

If you've not stumbled across it, check out the "&" (and in this case
"&!") in less. It's like a grep/filter for the buffer in less(1).

-tim



Christian Brabandt

unread,
Dec 20, 2020, 12:26:20 PM12/20/20
to vim_use

On So, 20 Dez 2020, Sven Guckes wrote:

> workaround:
> open the file with "less" and right after initiating search with '/'
> type '!' and the prompt will switch to "Non-match /". now enter
> eg "spool.exim.input" and less will skip all those lines. :-)
> that's one of the features i dearly miss with vim. oh, well.

Depending on what you want, you can use `:v`

Best,
Christian
--
Wie man sein Kind nicht nennen sollte:
Ray Genschirm

Tim Chase

unread,
Dec 20, 2020, 12:31:00 PM12/20/20
to A. Wik, vim...@googlegroups.com
you can use which only finds the start of the line:

/^\%(.*exim.input\)\@!

or if you want to match the entire line, you can use:

/^\%(\%(exim.input\)\@!.\)*$/

That breaks down to

^ from the start of the line
\%(…\)* zero or more of these things
\%(exim.match\)\@! at each of these places, this can't match
. accept a character here
$ all the way to the end of the line
(no partial line matches, or it would find
".spool/exim/inpu" (because "exim.input" doesn't yet
match)

-tim



Kenny Stauffer

unread,
Dec 29, 2020, 3:36:29 AM12/29/20
to vim_use
In a simple test file, this did what I think you're asking:    /\v^(.*exim[/]input)@!

Notice the use of @! instead of @<!

A. Wik

unread,
Oct 11, 2021, 7:45:40 PM10/11/21
to Tim Chase, vim_use
Thanks to all who replied to my thread!
Can you clarify the function of the dot? It appears that without it,
it finds only empty lines. With it, it finds any line not matching
"exim.input", including empty lines.

-aw

Tim Chase

unread,
Oct 13, 2021, 10:36:30 AM10/13/21
to vim...@googlegroups.com
On 2021-10-11 23:45, A. Wik wrote:
> > or if you want to match the entire line, you can use:
> >
> > /^\%(\%(exim.input\)\@!.\)*$/
> >
> > That breaks down to
> >
> > ^ from the start of the line
> > \%(…\)* zero or more of these things
> > \%(exim.match\)\@! at each of these places, this can't match
> > . accept a character here
> > $ all the way to the end of the line
> > (no partial line matches, or it would find
> > ".spool/exim/inpu" (because "exim.input" doesn't yet
> > match)
>
> Can you clarify the function of the dot? It appears that without
> it, it finds only empty lines. With it, it finds any line not
> matching "exim.input", including empty lines.

Sorry for the late reply. The "." is what lets the regex move
forward, roughly stating ".*" but at each of those "." locations,
before we accept that location, we assert that "exim.match" can't
match at that particular character.

this line contains exim match here

when the regex engine gets to the "e" in "exim match", the \@!
assertion fails, so the regex doesn't match that line, but on a line
like

hello

it starts at the beginning. /exim.match/ doesn't match there so the
"." accepts the "h", moving to the next char. /exim.match/ doesn't
match there either, so the "." accepts the "e". Repeat until it gets
to the end, having asserted that each ".", no /exim.match/ exists.

Hope that helps make a bit of sense of it?

-tim


A. Wik

unread,
Oct 14, 2021, 1:34:26 PM10/14/21
to vim_use
Hi all,
Yes, I think so. Is it because \@! is zero-width that it must be
paired with something (eg. ".") that does have width?

And it matches an empty line because of the \%( ... \)*?

-aw

Tim Chase

unread,
Oct 14, 2021, 1:40:54 PM10/14/21
to vim...@googlegroups.com
On 2021-10-14 17:34, A. Wik wrote:
> Yes, I think so. Is it because \@! is zero-width that it must be
> paired with something (eg. ".") that does have width?
>
> And it matches an empty line because of the \%( ... \)*?

Exactly, on both fronts. 👍

-tim


Reply all
Reply to author
Forward
0 new messages