views:

103

answers:

5

Hi everyone. I'd ideally like a vim answer to this:

I want to change

[*, 1, *, *] to [*, 2, *, *]

Here the stars refer to individual characters in the substring, which I would like to keep unchanged. For example

[0, 1, 0, 1] to [0, 2, 0, 1]
[1, 1, 1, 1] to [1, 2, 1, 1]

If people know how to do this in perl or python or whatever, that would be equally good. Cheers

+2  A: 

The following should do what you want:

:%s/\(\[[^,]*, *\)\(\d\)\([^]]*\]\)/\=submatch(1) . (submatch(2)+1) . submatch(3)/

In Vim, that is.

René Nyffenegger
+1  A: 

If those are strings in Python

>>> a = "[0, 1, 0, 1]"
>>> b = a[:4] + '2' + a[5:]
>>> b
'[0, 2, 0, 1]'

Lists are a little more trivial:

>>> c = [0, 1, 0, 1]
>>> c[1] = 2
>>> c
[0, 2, 0, 1]
>>>
Nick T
+4  A: 

This works :)

1,$s/\[\(\d\+\),\s\+\d\+,\s\+\(\d\+\),\s\+\(\d\+\)\]/[\1, 2, \2, \3]/g

or

%s/\[\(\d\+\),\s\+\d\+,\s\+\(\d\+\),\s\+\(\d\+\)\]/[\1, 2, \2, \3]/
codaddict
Would it be possible to extend these to, say six characters (this is the specific example I'm working with, and I don't understand the syntax used.
invisiblerhino
i.e.[*, 1, *, *, *, *] to [*, 2, *, *, *, *]
invisiblerhino
why are there some missing numbers in the new example ?
codaddict
Sorryi.e. [*, 1, *, *, *, *] to [*, 2, *, *, *, *]
invisiblerhino
Essentially I would like a number to become a 1 if it is a 1 in the first bit, a 2 if it is a 1 in the second, then a three if it is in the third and so on
invisiblerhino
+1  A: 

This one is shorter and a little more general purpose.

:%s/\(\[[^,],\s*\)1,/\12,/

The pattern doesn't care what is in the first slot of the list, and doesn't look at the rest of the list. This may be better, or worse, depending on what exactly you're trying to do.

bukzor
A: 

Note while using regexes for substitutions/modifications it is important to focus around the portion of the string you want to modify. Here is a short regex to do what you want (in perl), that illustrates this idea with your data.

Assuming $line contains the line you want to modify

 my $two=2;  
 $line =~ s/(,\s+)\d+/\1$two/;

The regex looks for the first comma, matches that and a arbitary number of spaces following the comma. This is remembered in the first back reference. After that it matches a arbitary number of digits. Finally it replaces what was matched by the string in the first backreference followed by 2. Applying this on your sample data gives
[0, 1, 0, 1] becomes [0, 2, 0, 1]
[1, 1, 1, 1] becomes [1, 2, 1, 1]

Jasmeet