2009/3/31 ivan budiselic <[email protected]>:
> On Tue, Mar 31, 2009 at 10:13 AM, Andreas Bernauer <[email protected]>
> wrote:
>>
>> ivan budiselic wrote:
>> >>> So, for the line:
>> >>>
>> >>> 1234 a a "a" a
>> >>>
>> >>> I'd like to get:
>> >>>
>> >>> 1234 b b "a" b
>> >>>
>> >>> The question is, is this possible and how.
>> >>>
>> >>> What I've tried is
>> >>> let line = substitute(line, '\([^\"]\{-}\)a', "\\1b", "g")
>> >>
>> >> ...because \{-} matches also 0 times; what you wanted is \{-1,}:
>> >>
>> >> let line = substitute('123 a "a" a', '\([^"]\{-1,}\)a', '\1b', 'g')
>> >>
>> >
>> > Ok, this worked pretty well, except that it doesn't work for cases when
>> > there's an 'a' at the start of the line (which I might be able to fix),
>> > and
>>
>> Allow matching 'start-of-line' (^) in front of 'a', too; see below.
>>
>> > the other problem which I wasn't specific enough about, and that is that
>> > I'd
>> > like the change to happen to 'a's outside of strings, so for example
>> > "xxxaxxx" shouldn't match. I guess this changes things quite a bit,
>> > sorry
>> > for not being clear enough.
>>
>> So, would you like further help? If yes, could you provide an example for
>> what
>> you want to achieve?
>>
>> s/\(^\|\s\)\zsa\ze\s\?/b/
>> works for
>> a 123 a a "xxxxaxxx" a
>> ==>
>> b 123 b b "xxxxaxxx" b
>
> Ok, so a complete example would be this:
>
> a 123 a "xy a xax xa a" xa ax xax "a" " a " " xa ax xax " a
>
> should result in
>
> b 123 b "xy a xax xa a" xb bx xbx "a" " a " " xa ax axa " b
>
> In words, all occurrences of 'a' outside of double quotes change to b, and
> all occurrences of 'a' inside double qoutes stay uncanged.
>
> The line you suggested doesn't handle the quotes. What I tried now is:
>
> let line = substitute(line, '^\%([^"]\|.\{-}".\{-}".\{-}\)\{-}\zsa\ze', 'b',
> 'g')
>
> Now, the problem I'm having is that I'm obviously missunderstanding the 'g'
> flag. This line does what I want, but only does the substitution for the
> first 'a' (so I can solve the problem by running it multiple times, until a
> match is possible, which is what I thought the 'g' flag is supposed to do).
[snip]

The 'g' flag will perform as many substitutions as match on the line
in a single attempt.  Therefore, it will only match once if the
pattern contains '^' as it will match at the start of the line.  If
you consider the effect of how you expect it to work, given a string:

bbbabab

If you did s/a/aa/g and it kept trying until it couldn't match, the
first attempt would make

bbbaabab

the second:

bbbaaabab

and so on until the computer gives up in an infinite-loop induced
panic.  Therefore, if you can imagine that the list of matches is
found (in this case character 4 and 6) and THEN each instance is
replaced, giving bbbaabaab.

I'm not sure of a good regular expression to do what you want, but it
might be simplest to use a construct like:

while match(line, regexp) != -1
    let line = substitute(line, regexp, subpattern, '')
endwhile

Just make sure that the result of the substitution can never create a
situation in which the regexp will match, or you'll be in an infinite
loop again.

An alternative way to do what you want would be to split the string on
the double quote character and then run a much simpler regular
expression on every other part:

" Split into component parts (keeping empty entries)
let components = split(line, '"', 1)

" Iterate through every other entry running substitution
let index = 0
while index < len(components)
    let components[index] = substitute(components[index], 'a', 'b', 'g')
    let index += 2
endwhile

" Recombine entries
let new_version_of_line = join(components, '"')

" (Untested)

Hope that helps a little.

Al

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply via email to