Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The following is roughly what I am trying to do in vim

:let g:ID = 1
:%s/^/\= g:ID | let g:ID = g:ID * 1.2/

Now, it looks like vim disregrads everything after the bar (that is the let g:ID = g:ID * 1.2 part.

I could of course write a function that multiplies g:ID with 1.2 and returns g:ID's value, but I'd like to forego this.

Thanks Rene

edit for clarity:

In vim-script, I can write multiple statements on one line if I use the bar (|) to chain them. So, instead of

let g:ID = 20
let g:ID = g:ID * 1.2
let g:ID = g:ID * 1.2

I could also write

  let g:ID = 20 | let g:ID = g:ID * 1.2 | let g:ID = g:ID * 1.2

Now, the \= thingy allows me to substitute a regular expression with a vim script expression. For example, I could do a

:%s/ABC/\=line(".")/

which would replace every occurence of ABC in my current buffer with the line number on which it is found.

Similarly a

:%s/^/\=g:ID/

would write the current value of g:ID at the beginning of each line in my buffer.

That's all fine and dandy, but I'd like to have more than one expression in the replacement part and was wondering if I could achieve that by chaining such expressions with the bar. In my case, I'd like to manipulate g:ID after every substitution call, hence

:let g:ID=20
:s/^/\=g:ID|let g:ID=g:ID * 1.2/

would result in writing 20 at the beginning of the first line in my buffer, 24 at the beginning of the second line in my buffer, 28.8 at the beginning of the third line in my buffer and so on.

I hope I made myself clearer now.

share|improve this question
1  
it is not instantly obvious what you want to achieve ... – akira Nov 5 '09 at 11:27
    
I want to chain two "commands" in the replacement part of a search-repacle pattern match. – René Nyffenegger Nov 5 '09 at 22:23
    
obviously i wasnt clear about what i was trying to say: edit your question so it becomes clearer without the comments :) – akira Nov 6 '09 at 6:24
    
Only expressions are allowed after \=. Or exactly one expression. | is command delimiter, and if you need to use let you either need a function (e.g. if you would need to use it in s/RE/\=EXPRESSION/g) or :g as @peth suggested. Is this a vim golf question? ;-) – Martian May 19 at 10:26
up vote 3 down vote accepted

You can use :global as its command is executed for every line.

:let g:ID = 1
:g//s//\=g:ID/ | let g:ID = g:ID + 1

If you want to constrain the replacement, either limit by the :global pattern, or prefix :global with a range, or both.

:10,20g/foo/s/^/\=g:ID/ | let g:ID = g:ID + 1

That should prepend the incremented g:ID for every line that matches foo from line 10 to 20 (inclusive).

share|improve this answer
    
Thank you. Although I hoped there would be a "more direct" way, your answer comes closest to what I wanted. – René Nyffenegger Apr 26 '11 at 23:17

You may need to define a function:

function! Accu(varname, mult)
  let old = {a:varname}
  let {a:varname} = {a:varname} * a:mult
  return old
endfunction

and use it this way:

:let g:ID = 1
:%s/^/\=Accu('g:ID', 1.2)/
share|improve this answer
    
Yes, I know that it is possible with a function. But sometimes I feel it's just not worth writing the function... that is, if I could go without... – René Nyffenegger Nov 17 '09 at 22:21

Try <bar> instead of | Have a look at: http://vim.wikia.com/wiki/Best_Vim_Tips

share|improve this answer
    
<bar> instead of | results in E15: invalid expression : g:ID <bar> let g:ID = ... and a E121: undefined variable bar – René Nyffenegger Nov 6 '09 at 10:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .