1

What I want to do is replace this:

<|Filename.ext|5|0|>

with

<|Filename.ext|5|0|>
<|Filename.ext|5|1|>
<|Filename.ext|5|2|>
<|Filename.ext|5|3|>
<|Filename.ext|5|4|>

I wrote a necessary regular expression:

<|\(\w\| \)\+\.\w\+|\d\{1,2}|0|>

So, substitution would go something like this:

 %s/<|\(\w\| \)\+\.\w\+|\d\{1,2}|0|>/REPLACEMENT/g

But what should REPLACEMENT actually be?

EDIT: Please, note that 5 in the example could be any other number: I am looking for a general solution. So, this:

<|Filename.ext|n|0|>

---->

<|Filename.ext|n|0|>
<|Filename.ext|n|1|>
<|Filename.ext|n|2|>
...
<|Filename.ext|n|n-2|>
<|Filename.ext|n|n-1|>

Sorry for not making this clear right away.

2
  • A substitution won't help, here, unless you already have all the identical lines you need.
    – romainl
    Aug 22, 2016 at 16:26
  • Not sure what was the purpose of your edit; as far as I understand, none of the answers below rely on the '5' to work.
    – mMontu
    Aug 22, 2016 at 16:52

4 Answers 4

3

If you have Vim version 7.4.754 or later you can do this simply with some copy/paste and g<C-a>:

yy4pf0<C-v>3jg<C-a>

Decomposing:

yy4p      duplicate the line 4 time and put you on the 2nd line
f0        go to the 0
<C-v>3j   start a visual block selection and go down 3 lines
g<C-a>    increment successively (1, 2, 3, 4)

Edit:

OP ask for a "general" solution,

You can replace 4 and 3 by N and N-1 to produce the same effect over N lines.

Have a look at : :h v_g_CTRL-A

10
  • 1
    Worth noting that you need a relatively recent version for this to work.
    – Tumbler41
    Aug 22, 2016 at 16:02
  • Nice catch, do you know where I can find this info?
    – nobe4
    Aug 22, 2016 at 16:05
  • 1
    Don't know exactly, but I knew about it because of this post by Christian.
    – Tumbler41
    Aug 22, 2016 at 16:12
  • 1
    Here it is: 7.4.754, from 2015-06-25. Like I said, it was really buggy at first. Aug 22, 2016 at 16:24
  • 1
    I searched the docs, then git blamed the docs, then looked around that date in the logs. :) It helped that I actually knew what to look for. Aug 22, 2016 at 16:29
2

Another way you could do this is with a macro:

qqyyp$bb^aq

Then n@q where n is how many additional lines you want

  • qq: record a macro in register "q"
  • yyp: yank the current line and put it below
  • $bb: move to the end of line and then back two "words" (This positions the cursor over the second number)
  • ^a: this is <C-a> and not a literal "^a". This increments the number by one.
  • q: end the macro
  • @q: play the macro at register "q". Can be prefaced with a number as stated before.
1

Try this:

%s/|\(0\)|>/\="|".(submatch(1)+1)."|>"/

The idea is to use \=, which allows to use an arbitrary expression for the replacement part. Note that it doesn't allows \1, thus the use of submatch().

More info: :help sub-replace-expression.

0

To add a solution only using :s, I would suggest

s/^.*$/\=map(range(0,split(getline("."),"|")[2]), 'join(split(getline("."), "|")[0:2] + [v:val] + split(getline("."), "|")[4:4], "|")')

This will work for any foo|bar|x|0|end, where foo and bar are string not containing the pipe character |, x is the number that indicates the number of repetitions, and end is an arbitrary string.

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.