简体   繁体   中英

Find first non-matching line in VIM

It happens sometimes that I have to look into various log and trace files on Windows and generally I use for the purpose VIM.

My problem though is that I still can't find any analog of grep -v inside of VIM: find in the buffer a line not matching given regular expression. Eg log file is filled with lines which somewhere in a middle contain phrase all is ok and I need to find first line which doesn't contain all is ok .

I can write a custom function for that, yet at the moment that seems to be an overkill and likely to be slower than a native solution.

Is there any easy way to do it in VIM?

I believe if you simply want to have your cursor end up at the first non-matching line you can use visual as the command in your global command. So:

:v/pattern/visual

will leave your cursor at the first non-matching line. Or:

:g/pattern/visual

will leave your cursor at the first matching line.

you can use negative look-behind operator @<!

eg to find all lines not containing "a", use /\\v^.+(^.*a.*$)@<!$

( \\v just causes some operators like ( and @<! not to must have been backslash escaped)

the simpler method is to delete all lines matching or not matching the pattern ( :g/PATTERN/d or :g!/PATTERN/d respectively)

I'm often in your case, so to "clean" the logs files I use :

:g/all is ok/d

Your grep -v can be achieved with

:v/error/d

Which will remove all lines which does not contain error .

It's probably already too late, but I think that this should be said somewhere.

Vim (since version about 7.4) comes with a plugin called LogiPat , which makes searching for lines which don't contain some string really easy. So using this plugin finding the lines not containing all is ok is done like this:

:LogiPat !"all is ok"

And then you can jump between the matching (or in this case not matching) lines with n and N .

You can also use logical operations like & and | to join different strings in one pattern:

:LP !("foo"|"bar")&"baz"

LP is shorthand for LogiPat , and this command will search for lines that contain the word baz and don't contain neither foo nor bar .

I just managed a somewhat klutzy procedure using the "g" command:

:%g!/search/p

This says to print out the non-matching lines... not sure if that worked, but it did end up with the cursor positioned on the first non-matching line.

(substitute some other string for "search", of course)

You can iterate through the non-matches using g and a null substitution:

:g!/pattern/s/^//c

If you reply "n" each time you wont even mark the file as changed.

You need ctrl-C to escape from the circle (or keep going to bottom of file).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM