Tuesday, April 26, 2011

Re: How to match A but not B

[Off-topic: What are you using to respond to the mailing list? It's
really annoying that your replies are never threaded with the thing to
which you're replying.]

On Tue, 26 Apr 2011, howard Schwartz wrote:

> Benjamen suggested:
:s/\%(jam\)\@<=en/in/

> /^\%(.*PPD\)\@!.*DEBIT
>
> I was aware of \@!, but the documention warned that .* will match
> everything including PPD, before the pattern can find PPD and exclude
> it. That is why one must know something about where a string is, to
> exclude it in a pattern match, no?

My solution doesn't care where the strings occur on a given line.

If at the start of the line \%(.*PPD\)\@! matches, then PPD occurs
nowhere on the line.

If, at that same point, .*DEBIT matches, then DEBIT appears on the line.

So, combining those two facts, it matches:
1. a line that contains DEBIT
2. which also doesn't contain PPD


> To quote the documentation:
>
> Using "\@!" is tricky, because there are many places where a pattern
> does not match. "a.*p\@!" will match from an "a" to the end of the
> line, because ".*" can match all characters in the line and the "p"
> doesn't match at the end of the line.
>
> Also the order seems wrong to me, but maybe this does not matter?

The order is reversed partly to overcome this problem.

The warning states that a.*p\@! will fail to discount 'a' followed by a
bunch of stuff then 'p'. In your example:

DEBIT.*\%(PPD\)\@!

would fail, because, for example:

line: DEBITxPPD

DEBIT matches 'DEBIT'
xP (or xPP or xPPD) matches the '.*'
at which point (PD$, D$, or $) PPD does not match.


> The string, DEBIT always occrs at the beginning of the line, if it
> occurs at all, and the string, PPD always occurs after DEBIT, if it
> occurs at all. Would the pattern not be:
>
> /^DEBIT.*\%(PPD\)\@!/
>
> And then there is the problem that .* will match PPD before the
> exclude operator \@! can exclude it?

Essentially, yes. That's what the documentation is warning you about.
And it's why the pattern as you've just written it will not work.

Given the constraints that DEBIT always begins the line, and that PPD
always comes after that if it appears at all, you can use:

/^DEBIT\%(.*PPD\)\@!

Note the position of the noncapturing parenthesis. The above is
equivalent to:

^DEBIT - a line starting with 'DEBIT'
\%(.*PPD\)\@! - not followed by a string ending with PPD
- (with the possible rest of the line after PPD left unspecified)

--
Best,
Ben

--
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: