13

I have the following SQL:

update am.PERMISSIONS set PRM_ORDER = 35 PRM_VISIBLE = b'1' where PRM_ID = 3;
update am.PERMISSIONS set PRM_ORDER = [35] PRM_VISIBLE = b'1' where PRM_ID = 7;
update am.PERMISSIONS set PRM_ORDER = [40] PRM_VISIBLE = b'1' where PRM_ID = 10;
update am.PERMISSIONS set PRM_ORDER = [45] PRM_VISIBLE = b'1' where PRM_ID = 11;
...

with square brackets I select the visual block, where i want to increase each number by 5. How do I do this?

3 Answers 3

18

Visually highlight the text in brackets:

Ctr+V2jl

Increment each number by five:

:norm 5Ctr+V Ctr+A Explanation:

:norm executes the whole command in normal mode. The Ctr+V is necessary, otherwise the cursor would jump back to the beginning of the line. Ctr+A increases a number by 1, and this is done 5 times. The visual range is inserted automatically after you pressed the colon.

EDIT: As Stephane correctly pointed out, the previous code increments the first number found on any line. Here's a better solution:

%s/\[\zs\d\+\ze\]/\=(submatch(0)+5)

It adds five to all integers within brackets. The \zs and \ze are used to exclude the brackets from the match and submatch returns the matched number.

7
  • It replaces the lines with -VC-A -VC-A -VC-A
    – J-unior
    Commented Apr 11, 2013 at 10:23
  • 1
    C-VC-A means press ctrl v, release, then press ctrl a, release.
    – Marco
    Commented Apr 11, 2013 at 10:26
  • 1
    That doesn't apply ^A on the visual selection, but at the start of every line marked by the selection (so for instance, if there were lines with numbers before the selected one, that would increase those and not the selected one) Commented Apr 11, 2013 at 13:00
  • 1
    You're totally right. It might work for the OPs use case, though. But I agree, my answer is wrong.
    – Marco
    Commented Apr 11, 2013 at 13:12
  • 1
    This plugin might be of some help to solve the problem, and I believe that if a plugin is necessary to do that kind of operations, it is not a simple matter of finding the right shortcut. Commented Apr 11, 2013 at 14:56
18

You do not need to leave visual mode to increase numbers, just use g

5 g Ctrl-a

5 ......... 5 times
g ......... globally
Ctrl-a .... increase numbers

Actually I have learned this trick in a vimgolf challenge.

5
  • 1
    I think this should be the correct answer. Suppose you wish to add a constant offset N to all numbers in a selected visual block. Typing in vim, without quotes, "5<Ctr+a>" works for me. If you want to add a constant offset N AND skip over values, "5g<Ctr+a>" works, as @SergioAraujo suggests. Don't need yet another plugin. Commented Dec 12, 2017 at 22:26
  • 1
    This is really nice. No need to do a big dirty substitute or install a seperate script. The help page for this is available as :h v_g_CTRL-A.
    – timss
    Commented Apr 25, 2018 at 11:00
  • 2
    This only changes the first number in each line for me
    – naught101
    Commented Jan 28, 2019 at 23:09
  • 3
    Adding the g just increments the amount added to the first number for each consecutive line (e.g. add 1 to line 1, 2 to line 2, etc.) rather than incrementing multiple numbers on a single line
    – Simon D
    Commented Jan 31, 2019 at 6:59
  • 1
    @SimonD you are right. Drop the 'g' to get them to all increment same amount "5 Ctrl-a". instead of "5 g Ctrl-a" which will multiply the value by the relative line number starting at 1.
    – pev.hall
    Commented Mar 11, 2021 at 3:06
3

These two commands are identical and will increment all numbers within a visual selection (even in a rectangle!).

:'<,'>s/\%V\d\+\%V/\=submatch(0)+1/g

:s/\%V\d\+\%V/\=submatch(0)+1/g

chopped up: :s / \%V \d\+ \%V / \=submatch(0)+1 / g

The \%V is a zero-width matcher that matches anywhere inside the current (or last) selection.

From the vim help:

\%V     Match inside the Visual area.  When Visual mode has already been
        stopped match in the area that gv would reselect.
        This is a /zero-width match.  To make sure the whole pattern is
        inside the Visual area put it at the start and just before the end of
        the pattern, e.g.:
                /\%Vfoo.*ba\%Vr
        This also works if only "foo bar" was Visually selected. This:
                /\%Vfoo.*bar\%V
        would match "foo bar" if the Visual selection continues after the "r".
        Only works for the current buffer.

Unfortunately this is not as clever as ctrl-a since it doesn't understand negative numbers.

You must log in to answer this question.

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