Wednesday, July 28, 2010

Re: Replace except enclosed by delimiters (")

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: