I have a file and I want to do the following.
- copy every n lines starting from m (m,m+n,m+2n, ...)
- copy line number 2, 5, 27, ... by specifying line numbers.
THanks
To copy every N lines, you can use :global
with an expression that selects the lines:
:let @a = ''
:g/^/if line('.') % 3 == 0 | yank A | endif
For explicit lines, I would sequentially call the :yank
command:
2yank a | 5yank A | 27yank A
This uses yanking into the uppercase register to append to it.
Besides the :g
solution, Ingo posted, you can also use an :s
command.
First you need to prepare the pattern. For example to explicitly match every third line,
you can use the pattern \%3l\|\%6l\|\%9l
, etc.
So first let's save the generated pattern inside a variable (to simplify it a bit, we only consider the first 100 lines):
:let lines=range(3,100,3)
This creates a list of all line numbers, starting from 3 and incrementing by 3, Note, if you need some special line numbers, that don't follow any arithemtic rule, simply define the list as this:
:let lines=[2,5,26,57,99]
Then we need to generate a pattern out of it, which we can use inside an :s
command:
:call map(lines, '''\%''.v:val.''l''')
This translates the line numbers into a pattern of the form \%
numberl
. So we have a pattern matching each desired line, but first we need to initalize a resulting list variable:
:let result = []
We can now feed this to the :s
command:
:exe ":%s/". join(lines, '.*\|'). '/\=add(result, submatch(0))/n'
All matching lines are now contained in the list result
and can e.g. be copied to the clipboard by using:
:let @+=join(result, "\n")
or you can paste it into a scratch buffer:
:new +exe\ append(0,result)
(Note, that the space between exe and the append call needs to be escaped).
Please also note, that this solution requires at least Vim Patch 7.3.627
Depending on the situation I would either use this method or the one pointed out by Ingo.