2

I have this text with numbers:

My numbers are 04, and 0005
My numbers are 05, and 0006
My numbers are 06, and 0035
My numbers are 07, and 0007
My numbers are 08, and 0009

This is the code I always used to increment or decrement numbers in a selection/block selection/column: p.e. increment the last 4 numbers in above text with 8:

 '<,'>s/\%V\<\d\{4}\>/\=submatch(0)+8/g

but I noted today that it does strange things. This is the output:

My numbers are 04, and 13
My numbers are 05, and 14
My numbers are 06, and 37 <---
My numbers are 07, and 15
My numbers are 08, and 17
  • it removes the leading zero's ( I would like to keep them if there are leading zero's and not add them if there aren't leading zero's)
  • it added 8 to all numbers except 37, where it added 2. (why?)

Can anyone help me to find a regex to add /subtract numbers from selection (or block selection) without losing the leading zero's?

note:
I noted that Control A + Control x keeps the leading zero's and does the work as I want but:
- I've seen that it can not be used in a substitute command ('<,'>s/)
- and I don't know how to add p.e. 200 to a list of numbers (200 x ?)

Reman
  • 7,931
  • 11
  • 55
  • 97
  • If it's any help, the way I prefer to do stuff like this is to write an external filter (eg, in perl), then use !/path/filter.pl on the block. This makes problems easier to solve, and the filters are easy to reuse and modify. – CodeClown42 Apr 17 '12 at 16:30

3 Answers3

4

leading zero makes number 8-based.

(0035)8 == (29)10

You can test in vim:

:echo 0035 == 29

It'll print 1(true).


Try this:

:%s/\(\<[0-9]\{4}\>\)\@=0*\([0-9]*\)/\=submatch(2)+8/
kev
  • 155,172
  • 47
  • 273
  • 272
  • "@Kev, I checked your regex. It works fine but I noted that it doesn't consider numbers when it is attached to a text character p.e. text22text or 22text. What do I have to change to make that work? (btw I suppose that it is not possible with a submatch regex to keep leading zero's isn't it?) – Reman Apr 18 '12 at 07:52
2

this?

:%s/\v[0-9]{4}/\=printf("%04d", substitute(submatch(0), '^0\+', '', 0)+8)/   

EDIT

@Remonn, you should give the right sample input in your question. the line above works on your example.

for your new requirement, take a look the line below:

input:

40
20
120
0500
230
0000000020
00000000000005000

vim cmd:

:%!awk '{if($0~/^0/){f="\%"length($0)"d";$0+=8; s=sprintf(f,$0); gsub(/ /,"0",s);}else s=$0+8;print s}'

will change the file to:

48
28
128
0508
238
0000000028
00000000000005008

in my cmd, I used '%', you can select (v) the numbers you want to do tricks with, then try with my cmd.

good luck

Kent
  • 189,393
  • 32
  • 233
  • 301
  • Thank you Kent, nice regex. However I noted that it put also for digits without leading zero's, leading zero's. I would like to keep the leading zero's if there are and not add them if there are not (as C-A / C-X does). – Reman Apr 17 '12 at 17:33
  • take these numbers: `40, 20, 120, 0500, 230` - above regex gives wrong results. Output: `48, 28, 200, 1300, 310` – Reman Apr 17 '12 at 21:02
  • "@Kent I spoke about a general regex in my question :) Thanks for the awk. It works fine. I'll keep it. However awk does not change the @/ numbers within in the text as kev's regex does. (Btw ho do you guys add the @Name before the comment?) – Reman Apr 18 '12 at 09:29
0

By default, Vim treats numbers beginning with 0 as octal.

For this reason I have this in my .vimrc:

set   nrformats-=octal  " Don't bother with octal, I never use it
johnsyweb
  • 136,902
  • 23
  • 188
  • 247