4

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

eli
  • 225
  • 2
  • 9

2 Answers2

7

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.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
1

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.

Christian Brabandt
  • 8,038
  • 1
  • 28
  • 32