3

I have a file similar to this:

aaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccc
dddddddddddddddddddd


aaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccc
dddddddddddddddddddd


aaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccc
dddddddddddddddddddd


I would like to join them to this:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

Until now I have done this by selecting blocks in (ctrl + v) and deleting them (x) and pasting them to the end of the first block (gg$p). This is very time consuming and I did not manage to get these things working in a macro.

How can I combine multiple blocks of lines?

1

5 Answers 5

5

I got the macro working:

qqgg5j^V4j$xgg$p9jV4kd
  • qq starts a macro called q
  • gg sets the startingpoint to the first line of the file
  • 5j goes down 5 lines (the start of the block below it)
  • ^V4j$ goes into column selection mode and selects the first block
  • x cut the content of the selection
  • gg$p paste it to the end of the first block
  • 9jV4kd delete the empty lines left after cutting

Typing in 2@q performs this action twice combining all lines

1
  • 1
    You could perhaps simplify the macro by deleting the empty lines before starting it: :g/^$/d, or something similar.
    – muru
    Mar 14, 2016 at 0:02
3

Another macro solution:

  • First go to the beginning of the first paragraph (in your example with 10G)
  • Then record macro: qqCtrl-Shit-V}$d5k$p0q
  • Reuse the macro with @q

The detail of the macro:

  • Ctrl-Shit-V start visual block mode
  • } select to the last line of the paragraph
  • $ select to the end of the line
  • d delete the selection
  • 5k go to the first line of the previous paragraph
  • $ got to the end of this line
  • p past the previously deleted paragraph
  • 0 go to the beginning of the line to be able to repeat the macro
3

What you do is almost .. graphical, so I'd use the mouse!

(of course you need :set mouse+=a)

Select a block with the mouse, then Ctrl-v y to yank the selection in "control-block" mode (<- that's the "secret" sauce). Still using the mouse, place cursor on top right character of the 2nd block. Paste (p).

Repeat :D ... That's all!

Yes, it's probably not feasible for a macro, or a large number of repetitions, but how long a line do you want to make?

2

Here's another way:

Make sure the a register is empty

:let @a = ''

Match all lines starting with aa, and then append them to the a register with y (the capital A means append, rather than overwrite). After that delete the line with d.

:g/^aa/y A | d

Now we can paste this at the start of the buffer (or anywhere else you'd like):

1G"aP

And join them:

4gJ

Repeat for bbb, ccc, etc.

The last step is perhaps easier done as:

vnnngJ

Which starts visual mode with v, n to skip past the lines, and then J to join them. You could also press J a few times in a row...

or:

v/^bbb<Enter>kgJ

Which searches for /^bbb, this has the advantage that the last used search pattern is now "primed" for our next :g invocation, which can now read:

:g//y A | d

Not specifying a pattern will use the last used search pattern (i.e. the @/ register).

2
  • You could use gJ instead of J to prevent Vim from inserting spaces. Mar 17, 2016 at 2:12
  • @JairLopez Ah yes, I forgot about that. Thanks! Mar 22, 2016 at 10:05
2

The interesting thing is how to deal with movement. If the lines to join start with same characters you can do (automated with a macro):

qq*"aD''*"AD''$"apj0

where:

  1. qq record a macro
  2. *"aD'' move to the line whith next char like first char of the first line, put the line in the register "a" and delete
  3. *"AD'' like 2. but append the line to the register

  4. $"ap paste register "a" at the end of the first line

  5. j0 move to the start of the next line

Then repeat the macro:

3@q

and delete the empty lines:

:$d

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.