Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
    
I think this has been asked before despite my not finding it at the time: vim delete all lines that do NOT contain a certain word – hippietrail Oct 30 '12 at 7:22
up vote 8 down vote accepted

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.

share|improve this answer
    
It seems :g is one of very many vim commands I never learned before - thanks! (-: – hippietrail Oct 28 '12 at 13:09
    
Why \( and \)? – Bernhard Oct 28 '12 at 13:38
1  
+, ?, |, {, }, (, and ) must be escaped to use their special function. – abhshkdz Oct 28 '12 at 13:40
    
I use :g and :v a lot. If, for some reason, :v doesn't stick you can use :g!. – romainl Oct 28 '12 at 20:28

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
share|improve this answer
    
While I do have vim installed on every platform I use, I usually only have awk when I'm on *nix. Lately I'm mostly on Windows. Hence I seek a vim-based answer. Thanks though. – hippietrail Oct 28 '12 at 13:07
    
I just realised that my initial solution wouldn't work... so if you do every use this, you should do it this way! – Kitchi Oct 28 '12 at 13:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .