I couldn't let this problem go while I didn't understand it. I think I got an alternative solution using \zs, which is faster and is recommended by VIM's documentation.
:%s/\("[^"]*"\)*\zs[^"]*/\L&/gc
It seems to work and is based on the principles that Tim laid down. Anyone agree?
Best
Felipe
On 28/07/2010, at 9:29 PM, Tim Chase wrote:
> On 07/27/10 22:43, fd wrote:
>> Well, I'm starting to use Vim and still getting the hang of it. I have
>> a problem where I need to replace a text to lowercase, except if the
>> text is enclosed by double quotes and I'm not quite getting it.
>> 
>> As an example give the input text
>> 
>> FOO, FOO, fooO, "foOO"
>> 
>> I want it to become
>> 
>> foo, foo, fooo, "foOO"
> 
> If you're just getting started with Vim, this is a rather tricky problem.  However, you've come to the right mailing list. :)
> 
> You can use the following:
> 
> :%s/\%(^\%([^"]\+\|"[^"]*"\)*\)\@<=[^"]\+/\L&/g
> 
> which roughly translates as
> 
> \%(...\)\@<=     assert that there are an even (including 0)
>                  number of quote-marks before this text
> [^"]\+           one or more non-quote characters comprising
>                  the actual match (the stuff we'll lower-case)
> 
> replaced with
> 
> \L&              the lowercase version of the match
> 
> The tricky part is the assertion:
> 
> ^                looking back to the beginning of the line
> \(...\|...\)*    you can have one of these two things
>                    zero or more times (the "*"):
> [^"]             either characters that aren't quotes (on
>                    the left side of the "\|"; or (on the
>                    right-side of the "\|")
> "                an opening quote
> [^"]             followed by stuff that isn't a quote
> "                followed by a closing quote
> 
> The assertion is then made with the "\@<=" which requires that vim look backwards (even before the match's start) to ensure this condition is met.
> 
> The only place it would break is if you expect to have embedded newlines crossing quotes:
> 
>  ABC, DEF, "GH
> IJK", LMN, OPQ
> 
> being treated as one line.  But if you do that, you get what you deserve for having such pathological input  ;-)  Though if you have this case, I'd use the "decorate, transform, undecorate" pattern:  (1) join lines with odd numbers of quotes until you don't have any more, joining with some unused character; (2) then perform the above transformation; (3) then replace all my placeholder characters with new-lines to get the line-breaks restored.  Then (4) I'd go smack the head of the person who created the file-format that allowed line-breaks in quoted text ;-)
> 
> -tim
> 
> 
> 
> 
> 
> 
> 
-- 
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
 
No comments:
Post a Comment