kojow7
kojow7

Reputation: 11394

Combining variable with submatch in Vim search and replace

I have several lines similar to this this:

insert into team (lowernum, uppernum, position, color1, color2) values (15, 16, 32, "red", "green");

I want to perform a search and replace in vim to change the third number (108 in this example) on every line so that it is increased by 15. The resultant line therefore will look like this:

insert into team (lowernum, uppernum, position, color1, color2) values (15, 16, 47, "red", "green");

I have tried several search and replace options, but have not figured out how to combined variables with submatches to get my desired result. An example of what I have tried is here:

:%s/\((\d\d, \d\d, \)\(\d\d\)/\=\1 submatch(2) + 15/g

Obviously, this gives an error, but I haven't been able to figure out the correct way to implement the replace clause. What is the correct way to do this?

Answer

Based on romainl's answer, this is the solution that worked for me:

:%s/\d\{1,}, \d\{1,}, \zs\(\d\{1,}\)/\=submatch(0) + 15/g

zs indicates the start of the pattern that will be replaced.

Upvotes: 0

Views: 634

Answers (2)

Patrick Günther
Patrick Günther

Reputation: 327

Having done a little bit of research, it doesn't seem possible to actually do arithmetics in search/replace operations in vim or sed. Though I would also be very interested if it actually is. I get, that what I suggested in my comment, an UPDATE statement would affect the whole table and not just the inserted values of that file.

So here is an alternative solution (assuming you're using mysql):

Replace every occurrence of 'team' in that file with 'tmp_team'.

Then add to the top of the file:

CREATE TABLE tmp_team LIKE team;

BEGIN EDIT: Now assuming that the team table has an auto_increment primary key on the column id, you have to drop that key in the tmp table and set all of it's values to null:

-- getting rid of the auto_increment property:
ALTER TABLE tmp_team MODIFY id INT DEFAULT NULL;
-- dropping primary key:
ALTER TABLE tmp_team DROP PRIMARY KEY;
UPDATE tmp_team SET id = NULL;

END EDIT

And to the bottom of the file:

UPDATE tmp_team SET position = position+15;
-- inserting NULL values into an auto_increment column, assigns
-- correct values to the new entries
INSERT INTO team SELECT * FROM tmp_team;
DROP TABLE tmp_team;

This way you would only affect the position values of the teams in that file.

Upvotes: 0

romainl
romainl

Reputation: 196586

This should do the trick:

:s/\d\{2,}, \d\{2,}, \zs\(\d\{2,}\)/\=submatch(0) + 15

Upvotes: 3

Related Questions