tags:

views:

361

answers:

10

How can I select all lines that do not contain the word "hello" in VIM? I need it yanked and then saved to a file. How can I do it? I am looking for something like:

:v/!(hello) > file

+8  A: 

Provided you have grep on your system, you can use this command:

:!grep -v hello % > file
too much php
'%' is not a special character for grep, it is a special character for the vim command line, see :help cmdline-special
+4  A: 

I usually do this with some variation of

:g/hello/d

i.e. delete everything containing "hello", then select, yank, or whatever needs to be done, and finally revert back hitting u. I find this is less mentally taxing then building command line pipes.

d.hoeffer
This is much shorter command than mine to the same problem.
Masi
+1  A: 

Select and write to a new file:

:g/hello/ . w!>> file
fgm
+1 - but you need to switch that g/ to v/ to select all the lines that don't contain hello
rampion
What does the . mean?
Masi
A: 

After Vim command

:let @a='' | g!/hello/normal "Ayy

you will have all the lines that doesn't have 'hello' in the register 'a'. You can paste its value with "ap normal command or put this value to system clipboard with

:let @*=@a

And you can use then 'Ctrl+V' on Windows or 'Cmd+V' on Mac Os or 'middle mouse click' on Linux to paste the text.

Brief description of the magic:

@a is a Vim variable that is bound to value stored in the 'a' register.
"ap, "bp, "cp, .. is the key combination in the Vim normal mode to past a value from the specific register.
@* is a Vim variable that is bound to the System clipboard.
let @* = @a put value from the register 'a' to the System clipboard.

Add this to your .vimrc or create file withing plugin dir.

function s:copy_unmathced_lines(pattern)
   let result_lines = []

   for line in getline(1, '$')
      if line !~ a:pattern
         call add(result_lines, line)
      endif
   endfor

   let @* = join(result_lines, "\n")
endfunction

command -nargs=1 CopyUnmatchedLines call s:copy_unmathced_lines(<q-args>)

Use case is simple:

CopyUnmatchedLines hello

and then just use paste command in any editor.

Mykola Golubyev
This answer seems to be very cool, but somehow hard to understand. Perhaps, someone could clarify in an reply how things work beneath the surface. What are the weird things such as "@a" and "let"? Ex, vim or something else?
Masi
+10  A: 
:g!/hello/ yank A

The lines are now stored in register a, to paste them do "ap

Edit: Can be abbreviated to

:g!/hello/y A

For those interested in what this means to vim:

:g = global search
! = negation of boolean test that follows
/hello/ = regular expression to match "hello"
y = command to perform upon each matched line, in this case "yank"
A = register argument to "yank" command. In this case register 'a' but in the form of upper case meaning append to the register rather than replace.

:v is equivalent to :g!
dysmsyd
ooh, thanks for that dysmsyd. I'll actually use that a lot.
This is awesome! Thank you for sharing this.
Masi
Your answer does not seem to answer the rest of the question: "> file". Let's people re-evaluate replies in a bounty.
Masi
I am particularly interested about the ways control your buffer: saving, editing and finally redirecting to a file.
Masi
+7  A: 

An alternative I did not see mentioned so far, is redirecton.

So for your case this would be

:redir > file
:g!/hello/
:redir END

See also

:help redir
:help verbosefile
+5  A: 

fgm's answer was nearly there

:v will select lines that do NOT match

so the following will append lines not containing "hello" to a file called eee, creating it if required.

:v/hello/ . w!>>eee
dysmsyd
A: 

A practical Example with Blixtor's snippet: Email friends lost with ":verbosefile".

I. open manual ":e /tmp/new_file" and ":h verbosefile", then let's copy-cat blixtor's tip:

:redir > /tmp/verbosefile_instructions
:g/verbosefile/
:redir END

II. affirm that you follow the standard rules about the legth of your emails, and source the standard greetings:

:match ErrorMsg /\%>73v.\+/
:so /bin/greetings.vim

III. Send the file with Mutt.

Masi
A: 

Example about visual selection and copying: Suppose you want to separate a part:

  1. visual-select it and press ":"

  2. then use the command:

    :'<,'> ! > ../new_file_in_a_subdirectory

Error: the colours will be copied to the file, and it is not actually coping rather cut-and-paste.

Masi
+1  A: 

Pretty straight forward;

:v/hello/ |redir >> file