Several methods allow you to copy all search matches (search hits). Usually, you want to copy each line which contains text matching your search pattern, but you can also copy just the matching text. The tip starts with methods to easily list search hits, without copying them, then shows how to copy matches, or matching lines. Similar techniques, also shown below, can be used to delete all matching lines.

Copying or deleting search matches is easy when simple search patterns are used. The techniques shown here also work with multiline matches.

To view only the parts of a file that match your pattern, see Folding with Regular Expression. You can fold away non-matching lines, and use zr to reveal more context around the search hits.

Another approach is to put the cursor on a word of interest, then type [I to list occurrences.

Copy or delete matching lines

Matching lines can be copied to the clipboard, so they can be pasted into another application.

To copy all lines containing a search pattern, use the following (see here). The first command clears register a (:help q). The second appends all matching lines to that register (:help quotea). The third copies register a to the clipboard (register +) for easy pasting into another application. Replace pattern with what you want to search for, or omit it (:g//y A) to use the last search.

qaq
:g/pattern/y A
:let @+ = @a

The above procedure captures only the first line of each match. See below for copying multiline matches.

It is also easy to delete lines containing single-line matches. The first of the following commands deletes all lines containing pattern, while the second deletes all lines matching the last search:

:g/pattern/d
:g//d

Use :v//d to delete all lines that do not match the last search pattern, or
:v/pattern/d to delete all lines that do not match the given pattern.

If a search pattern may find multiline matches, the above procedures to delete matching lines fail. In that case, use the following which works with any kind of match.

Copy matches

The simple script shown here copies only the text that matches search hits. It works with multiline matches. First save the buffer because the script changes it (the changes should result in the same text, but it is safer to save first). After sourcing the following, search for a pattern, then enter :CopyMatches to copy all matches to the clipboard, or :CopyMatches x where x is any register to hold the result.

The above code works after any search, including searches which match text in more than one line. The expression used in the substitute replacement uses len() as a trick to call add() (which returns the list after appending a match to it).

Use the following to copy matches from all buffers to register a:

:let @a = ''
:bufdo CopyMatches A

In the following text, use search pattern \<A\_.\{-}Z\> (any word beginning with A, followed by any characters including newline, as few as possible, to a word ending with Z) to test :CopyMatches (it copies four hits: A1...1Z and A2...2Z and A3...3Z and A4...4Z):

Copy matches or lines

The script in this section provides more features. It works with multiline matches, and provides a CopyMatches command to copy only matching text, as well as a CopyLines command to copy all lines that contain a match.

Each command accepts a range of lines, and can copy into any register (by default, the clipboard). The first of the following commands copies all text matching the last search into the clipboard, while the second copies all matches in lines 1 to 10 inclusive to register a, and the third copies matches from the current line (.) to the default register ("):

:CopyMatches
:1,10CopyMatches a
:.CopyMatches "

Matches can be copied into a scratch buffer instead of a register. To do that, use - as the register name. If a bang (exclamation mark) is used, the line number of each match is included. Also, a search pattern can be entered on the command line. For example, the following commands display the results for two searches in the same scratch buffer. Search matches, with line numbers, are displayed for all words beginning with 'a', and for all strings of digits. Enter the first command, then switch back to the original buffer while keeping the scratch window open, then enter the second command:

GetMatches() alternative

The following shows an alternative method to copy matches. This script is less useful than others in this tip as it does not handle multiline matches. However, the technique may be of interest as it shows how to use the match() function. In addition, it does not involve changes to the current buffer.

" Return list of matches for given pattern in given range.
" This only works for matches within a single line.
" Empty hits are skipped so search for '\d*\ze,' is not stuck in '123,456'.
" If omit match() 'count' argument, pattern '^.' matches every character.
" Using count=1 causes text before the 'start' argument to be considered.
function! GetMatches(line1, line2, pattern)
let hits = []
for line in range(a:line1, a:line2)
let text = getline(line)
let from = 0
while 1
let next = match(text, a:pattern, from, 1)
if next < 0
break
endif
let from = matchend(text, a:pattern, from, 1)
if from > next
call add(hits, strpart(text, next, from - next))
else
let char = matchstr(text, '.', next)
if empty(char)
break
endif
let from = next + strlen(char)
endif
endwhile
endfor
return hits
endfunction

Comments

Just after my last major update to this tip (a week ago), I found a note pointing to a vim_use thread where ZyX showed a simple yet brilliant technique for handling multiline matches. Testing shows that the posted code is not entirely correct as it misses multiline matches that occur in the same line after a short match. However, I have done extensive modifications and the resulting script (now in this tip) is sensational. JohnBeckett 03:31, May 3, 2012 (UTC)