Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search and Replace with incremented values in Vim

Tags:

replace

vim

Lets say I wrote a simple CSS rule like this:

.star_10 {   background: url(stars.png) no-repeat 0 0; } 

And I need 10, so I copied it 9 times.

.star_10 {   background: url(stars.png) no-repeat 0 0; } .star_10 {   background: url(stars.png) no-repeat 0 0; } .star_10 {   background: url(stars.png) no-repeat 0 0; } .star_10 {   background: url(stars.png) no-repeat 0 0; } .star_10 {   background: url(stars.png) no-repeat 0 0; } 

etc.

Now I want to change the star_10 and 0 0 with incremented values so it looks like this:

.star_10 {   background: url(stars.png) no-repeat 0 0; } .star_9 {   background: url(stars.png) no-repeat 0 -18px; } .star_8 {   background: url(stars.png) no-repeat 0 -36px; } .star_7 {   background: url(stars.png) no-repeat 0 -54px; } 

and so on...

So how can I search/replace every instance, do a calculation and write it?

like image 919
Fred Fickleberry III Avatar asked Feb 09 '11 22:02

Fred Fickleberry III


People also ask

How do you do a search and replace string in Vim?

The simplest way to perform a search and replace in Vim editor is using the slash and dot method. We can use the slash to search for a word, and then use the dot to replace it. This will highlight the first occurrence of the word “article”, and we can press the Enter key to jump to it.

How do I change occurrences in vim?

Press y to replace the match or l to replace the match and quit. Press n to skip the match and q or Esc to quit substitution. The a option substitutes the match and all remaining occurrences of the match. To scroll the screen down, use CTRL+Y , and to scroll up, use CTRL+E .

How do you replace a whole word in Vim?

To quickly change a word you can use cw , caw or ciw . Use c$ or just C to quickly change from the cursor to the end of a line, cc to change an entire line, or cis for a sentence. The standard change word command requires you to type cw , then a new word, then press Escape.


2 Answers

You can do it easily with a macro. Lets say you have only this:

.star_10 {   background: url(stars.png) no-repeat 0 0; } 

Place your cursor over the first dot (in .star10) and type the following in normal mode:

qa3yy3jp^Xjt;18^Xk0q 

Explaining:

  1. qa will start a macro recording in register "a".
  2. 3yy will yank (copy) the following 3 lines.
  3. 3j will place the cursor 3 lines down.
  4. p will paste the past yanked text.
  5. ^X (ctrl+x) will decrement the star class number.
  6. j will place your cursor one line down.
  7. t; will place your cursor before the next ; in the current line.
  8. 18^X will decrement the y coordinate of backround by 18;
  9. k will put the cursor one line up,
  10. 0 will put the cursor at the beggining of the line.
  11. q will finish the macro recording.

After that, you may have something like this.

.star_10 {   background: url(stars.png) no-repeat 0 0; }  .star_9 {   background: url(stars.png) no-repeat 0 -18; } 

That's it. Just place your cursor at the dot on .star_9 and press 8@a to execute the macro recorded in register a eight more times.

like image 65
Herberth Amaral Avatar answered Sep 23 '22 20:09

Herberth Amaral


You can use the s/pattern/replace construct with the \= symbol in order to evaluate a function or expression, as shown:

Decrementing the .star_10:

let g:decr = 11  fu! Decr()    let g:decr = g:decr - 1   return g:decr endfu  :%s/.star_10/\=".star_" . Decr()/ 

Similarly, you'd do

let g:decr_18 = 18 fu! Decr18()    let g:decr_18 = g:decr_18 - 18   return g:decr_18 endfu 

and then replace the 0 0; with a

:%s/no-repeat 0 0;/\="no-repeat 0 " . Decr18() . "px"/ 

For both functions, a (global) variable is declared that is manipulated within the functions and returned. The functin itself is called for every line matching the pattern. the pattern is substituted with the expression following the \=.

like image 28
René Nyffenegger Avatar answered Sep 25 '22 20:09

René Nyffenegger