1

I’m exploring Vim’s capabilities and somehow stumbled upon this task. It’s constructed, but I’m curious: Is there a one-liner colon command that can

  1. find the first line that matches a pattern p (say, begins with „bla“)
  2. find the first line after this line that doesn’t match p and
  3. move lines 4-5 after the line found in 2.?

The order of 1.-3. doesn’t matter for purposes of execution, that’s just to explain what I’m thinking of achieving.

Thanks guys! Vim is so great.

0
3

Use the following syntax:

:/\(bla[^\n]*\)\+\zs/;4,5m.

which finds multiple (+) occurrences of bla followed by new line characters ([^\n]), then place the cursor (;) where we set our start of match (\zs) and move our range of lines (4,5) at the current cursor position. See: :help :/.

To insert lines at the end of the whole pattern (not after first line of match), change bla[^\n] into \nbla, e.g.:

:/\(\nbla\)\+\zs/;4,5m.

Instead of current cursor position (.), you can also use variety of different addresses to move the lines into, like \/ (the next line where the previously used search pattern matches or other addresses; see :help {address}).

5
  • I think this should have a [^\n]* inserted after the bla, since OP said "begins with" bla, not "only contains" bla.
    – Wildcard
    Oct 29 '15 at 12:50
  • @Wildcard Thanks, probably I misunderstood 2. step, I've expanded my answer based on your advice. Hope that's clearer now.
    – kenorb
    Oct 29 '15 at 13:00
  • Yep. I like this approach because it doesn't require the regex be typed in twice.
    – Wildcard
    Oct 29 '15 at 13:03
  • Having the pattern just once is a plus. I got it working after what looks like correcting a misunderstanding, because bla is just the start of the line. /\(\nbla.*\)\+\zs/;4,5m. Nov 15 '15 at 8:58
  • I also like learning that I can move the cursor with ;. Nov 15 '15 at 9:10
2

You can do something like this:

:/^bla/,/^\(bla\)\@!/;4,5 m .

Here :/^bla/,/^\(bla\)\@!/; searches for the first line that begins with bla, then finds the next line that does not begin with bla and puts the cursor there (with ;). The next part, 4,5 m . then moves lines 4 and 5 to the cursor position ..

Note that this requires well thought out regexps, and I was not able to find a way to reuse the first regexp in the second.

3
  • What is your thinking in using \@! here? I admit I don't know what this is supposed to do, but it's interesting! Nov 15 '15 at 8:52
  • \@! is used to prevent a match of the previous atom, that is, it matches with zero width if the previous part does not match. Nov 15 '15 at 16:00
  • To make it more clear: /^\(bla\)\@!/ matches any line that does NOT start with bla. This is done with the \@! multi. I find the list in :h pattern-overview very good to show the difference between the different patterns. Nov 16 '15 at 21:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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