babba_motif
babba_motif

Reputation: 3

How to use VIM visualblock to incrementally increase numbers in a block

I wish to reorder the records in this long file in the column of 3 digits after the ATOM record to start at '1' rather than '534'. Each line represents an atom in a large protein file. I can select the block of text with visual block (ctrl+v) but not sure what to next. I've searched similar problem but the suggested code doesn't work.

I'm using VIM editor and not too familiar with coding I'm afraid.

Eg. Someone suggested selecting the block then use ":I" (didn't work). Other suggestion: select block then use "ctrl+a" (didn't work). Would anyone have the correct VIM method by any chance? Many thanks

ATOM 534 C ACE A 0 10.207 22.900 174.325 1.00 0.00 C

ATOM 535 O ACE A 0 10.093 22.142 173.352 1.00 0.00 O

ATOM 536 CA ACE A 0 11.342 22.737 175.312 1.00 0.00 C

ATOM      1 N PRO A 1 9.225 23.976 174.522 1.00 32.27 N

ATOM      2 CA PRO A 1 8.230 23.902 173.411 1.00 32.77 C

ATOM      3 C PRO A 1 8.827 23.261 172.170 1.00 30.28 C

Upvotes: 0

Views: 643

Answers (3)

SergioAraujo
SergioAraujo

Reputation: 11810

You can try the following:

Ctrl-v ..........................Select the block with the numbers
:'<,'>s/\d+/1 ...................Substitute all numbers by 1
gv ..............................Repeat the selection
o ...............................jump to the beginning of the selection
j ...............................goes to the seccond line 
g Ctrl-a.........................increase the numbers

OBS: If you already have selected the range once use gv to reselect and then follow with the substitution then reselect and use g Ctrl-a. See more on the help system :h g_Ctrl-a

I using j for not increase the first number

If something gets wrong just type:

:e!

this gets your buffer at the point it was when you opened it.

Upvotes: 0

Ingo Karkat
Ingo Karkat

Reputation: 172590

To substitute with an increasing number, we can use a register as the counter; as setreg() returns 0 on success, we can invoke it purely for its side effects in the expression, as part of :help sub-replace-expression.

:let @a = 1 | %s/^ATOM \+\zs\d\+/\=@a + setreg('a', @a + 1)/g

The pattern asserts (with :help /\zs) that there's the ATOM before the number, to avoid other matches.

Fixed-width Variant

If you want to keep identical width despite the changing numbers, the following changes need to be done:

  1. match the whole field, including leading whitespace
  2. use :help printf() for a right-aligned fixed-width formatting of the number (%3d)
:let @a = 1 | %s/^ATOM \zs\s*\d\+/\=printf('%3d', @a + setreg('a', @a + 1))/g

Upvotes: 1

Red Cricket
Red Cricket

Reputation: 10470

Here is what you can do.

Given this text file:

$ cat file
Eg. Someone suggested selecting the block then use ":I" (didn't work). Other suggestion: select block then use "ctrl+a" (didn't work). Would anyone have the correct VIM method by any chance? Many thanks
ATOM 534 C ACE A 0 10.207 22.900 174.325 1.00 0.00 C
ATOM 535 O ACE A 0 10.093 22.142 173.352 1.00 0.00 O
ATOM 536 CA ACE A 0 11.342 22.737 175.312 1.00 0.00 C
ATOM      1 N PRO A 1 9.225 23.976 174.522 1.00 32.27 N
ATOM      2 CA PRO A 1 8.230 23.902 173.411 1.00 32.77 C
ATOM      3 C PRO A 1 8.827 23.261 172.170 1.00 30.28 C

Hi there just more stuff in the file.

Open the file in vim …

enter image description here

Now type

:2,7!sort -k2 -n

Hit enter and you should see …

enter image description here

Then just :wq and you're good to go!

Upvotes: 1

Related Questions