2

In Vim I often find I'm only interested in lines containing a certain string of text and want to delete all other lines.

It's easy to match lines containing a string:

:s/^.*foo.*\n//

What I normally end up doing is two passes, one to "flag" all the lines I want with a special first character:

:s/^\(.*foo.*\)$/X\1/

And in the second pass it's easy to do a negative match for one character in a fixed position, so I delete all the lines without my string thus:

:s/^[^X].*\n//

But isn't there a much more straightforward way to do this with just a single pass? What am I missing?

hippietrail
  • 4,605

2 Answers2

11

This would delete all lines that don't contain foo.

:g/^\(.*foo\)\@!.*$/d

Instead, you could also use :v to reverse the sense of search pattern.

:v/\(foo\)/d

You can read more about the way :g and :v work here.

And more on defining ranges, use of metacharacters etc. for search and replace here.

abhshkdz
  • 722
0

Well, if your aim is only to remove the lines with the text, that can be easily done with awk like so :

awk '/regex/{print}' filename

Meaning awk will act on filename. You can either pipe it to a new filename or the same filename, like this -

   awk '/regex/{print}' filename > filename.tmp && mv filename.tmp filename
Kitchi
  • 285